nim-libp2p-experimental/libp2p/stream/lpstream.nim

123 lines
4.1 KiB
Nim
Raw Normal View History

2019-09-01 17:31:24 +00:00
## Nim-LibP2P
2019-09-24 17:48:23 +00:00
## Copyright (c) 2019 Status Research & Development GmbH
2019-09-01 17:31:24 +00:00
## Licensed under either of
## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
## * MIT license ([LICENSE-MIT](LICENSE-MIT))
## at your option.
## This file may not be copied, modified, or distributed except according to
## those terms.
import oids
import chronicles, chronos
2019-09-01 17:31:24 +00:00
type
2019-09-01 17:31:24 +00:00
LPStream* = ref object of RootObj
isClosed*: bool
closeEvent*: AsyncEvent
when chronicles.enabledLogLevel == LogLevel.TRACE:
oid*: Oid
2019-09-01 17:31:24 +00:00
LPStreamError* = object of CatchableError
LPStreamIncompleteError* = object of LPStreamError
LPStreamIncorrectDefect* = object of Defect
2019-09-01 17:31:24 +00:00
LPStreamLimitError* = object of LPStreamError
LPStreamReadError* = object of LPStreamError
par*: ref Exception
LPStreamWriteError* = object of LPStreamError
par*: ref Exception
LPStreamEOFError* = object of LPStreamError
2019-09-01 17:31:24 +00:00
2019-09-01 21:56:00 +00:00
proc newLPStreamReadError*(p: ref Exception): ref Exception {.inline.} =
var w = newException(LPStreamReadError, "Read stream failed")
2019-09-01 17:31:24 +00:00
w.msg = w.msg & ", originated from [" & $p.name & "] " & p.msg
w.par = p
result = w
proc newLPStreamWriteError*(p: ref Exception): ref Exception {.inline.} =
var w = newException(LPStreamWriteError, "Write stream failed")
w.msg = w.msg & ", originated from [" & $p.name & "] " & p.msg
w.par = p
result = w
proc newLPStreamIncompleteError*(): ref Exception {.inline.} =
result = newException(LPStreamIncompleteError, "Incomplete data received")
proc newLPStreamLimitError*(): ref Exception {.inline.} =
result = newException(LPStreamLimitError, "Buffer limit reached")
proc newLPStreamIncorrectDefect*(m: string): ref Exception {.inline.} =
result = newException(LPStreamIncorrectDefect, m)
2019-09-01 17:31:24 +00:00
proc newLPStreamEOFError*(): ref Exception {.inline.} =
result = newException(LPStreamEOFError, "Stream EOF!")
2019-09-04 06:40:11 +00:00
method closed*(s: LPStream): bool {.base, inline.} =
s.isClosed
method readExactly*(s: LPStream,
pbytes: pointer,
nbytes: int):
Future[void] {.base, async.} =
2019-10-03 19:29:58 +00:00
doAssert(false, "not implemented!")
2019-09-01 17:31:24 +00:00
method readOnce*(s: LPStream,
pbytes: pointer,
nbytes: int):
Future[int]
{.base, async.} =
2019-10-03 19:29:58 +00:00
doAssert(false, "not implemented!")
2019-09-01 17:31:24 +00:00
proc read*(s: LPStream, nbytes: int): Future[seq[byte]] {.async, deprecated: "readExactly".} =
# This function is deprecated - it was broken and used inappropriately as
# `readExacltly` in tests and code - tests still need refactoring to remove
# any calls
# `read` without nbytes was also incorrectly implemented - it worked more
# like `readOnce` in that it would not wait for stream to close, in
# BufferStream in particular - both tests and implementation were broken
var ret = newSeq[byte](nbytes)
await readExactly(s, addr ret[0], ret.len)
return ret
proc readLine*(s: LPStream, limit = 0, sep = "\r\n"): Future[string] {.async, deprecated: "todo".} =
# TODO replace with something that exploits buffering better
var lim = if limit <= 0: -1 else: limit
var state = 0
try:
while true:
var ch: char
await readExactly(s, addr ch, 1)
if sep[state] == ch:
inc(state)
if state == len(sep):
break
else:
state = 0
if limit > 0:
let missing = min(state, lim - len(result) - 1)
result.add(sep[0 ..< missing])
else:
result.add(sep[0 ..< state])
result.add(ch)
if len(result) == lim:
break
except LPStreamIncompleteError, LPStreamReadError:
discard # EOF, in which case we should return whatever we read so far..
2019-09-01 17:31:24 +00:00
method write*(s: LPStream, msg: seq[byte], msglen = -1)
{.base, async.} =
2019-10-03 19:29:58 +00:00
doAssert(false, "not implemented!")
2019-09-01 17:31:24 +00:00
proc write*(s: LPStream, pbytes: pointer, nbytes: int): Future[void] {.deprecated: "seq".} =
s.write(@(toOpenArray(cast[ptr UncheckedArray[byte]](pbytes), 0, nbytes - 1)))
2019-09-01 17:31:24 +00:00
proc write*(s: LPStream, msg: string, msglen = -1): Future[void] =
let nbytes = if msglen >= 0: msglen else: msg.len
s.write(@(toOpenArrayByte(msg, 0, nbytes - 1)))
2019-09-01 17:31:24 +00:00
method close*(s: LPStream)
{.base, async.} =
2019-10-03 19:29:58 +00:00
doAssert(false, "not implemented!")