Add ability to create copies of AsyncStreams.

This commit is contained in:
cheatfate 2019-06-18 20:11:13 +03:00
parent c113aa1be7
commit 31f4dc3096
No known key found for this signature in database
GPG Key ID: 46ADD633A7201F95
1 changed files with 280 additions and 180 deletions

View File

@ -275,6 +275,9 @@ proc readExactly*(rstream: AsyncStreamReader, pbytes: pointer,
raise newAsyncStreamIncompleteError()
except:
raise newAsyncStreamReadError(getCurrentException())
else:
if isNil(rstream.readerLoop):
await readExactly(rstream.rsource, pbytes, nbytes)
else:
var index = 0
while true:
@ -308,6 +311,9 @@ proc readOnce*(rstream: AsyncStreamReader, pbytes: pointer,
result = await readOnce(rstream.tsource, pbytes, nbytes)
except:
raise newAsyncStreamReadError(getCurrentException())
else:
if isNil(rstream.rsource):
result = await readOnce(rstream.rsource, pbytes, nbytes)
else:
while true:
let datalen = rstream.buffer.dataLen()
@ -352,6 +358,9 @@ proc readUntil*(rstream: AsyncStreamReader, pbytes: pointer, nbytes: int,
raise newAsyncStreamLimitError()
except:
raise newAsyncStreamReadError(getCurrentException())
else:
if isNil(rstream.readerLoop):
result = await readUntil(rstream.rsource, pbytes, nbytes, sep)
else:
var
dest = cast[ptr UncheckedArray[byte]](pbytes)
@ -410,6 +419,9 @@ proc readLine*(rstream: AsyncStreamReader, limit = 0,
result = await readLine(rstream.tsource, limit, sep)
except:
raise newAsyncStreamReadError(getCurrentException())
else:
if isNil(rstream.readerLoop):
result = await readLine(rstream.rsource, limit, sep)
else:
var res = ""
var
@ -460,6 +472,9 @@ proc read*(rstream: AsyncStreamReader, n = 0): Future[seq[byte]] {.async.} =
result = await read(rstream.tsource, n)
except:
raise newAsyncStreamReadError(getCurrentException())
else:
if isNil(rstream.readerLoop):
result = await read(rstream.rsource, n)
else:
var res = newSeq[byte]()
while true:
@ -507,6 +522,9 @@ proc consume*(rstream: AsyncStreamReader, n = -1): Future[int] {.async.} =
raise newAsyncStreamLimitError()
except:
raise newAsyncStreamReadError(getCurrentException())
else:
if isNil(rstream.readerLoop):
result = await consume(rstream.rsource, n)
else:
var res = 0
while true:
@ -555,6 +573,9 @@ proc write*(wstream: AsyncStreamWriter, pbytes: pointer,
raise newAsyncStreamWriteError(resFut.error)
if resFut.read() != nbytes:
raise newAsyncStreamIncompleteError()
else:
if isNil(wstream.writerLoop):
await write(wstream.wsource, pbytes, nbytes)
else:
var item = WriteItem(kind: Pointer)
item.data1 = pbytes
@ -583,12 +604,15 @@ proc write*(wstream: AsyncStreamWriter, sbytes: seq[byte],
raise newAsyncStreamIncorrectError("Zero length message")
if isNil(wstream.wsource):
var resFut = write(wstream.tsource, sbytes)
var resFut = write(wstream.tsource, sbytes, msglen)
yield resFut
if resFut.failed:
raise newAsyncStreamWriteError(resFut.error)
if resFut.read() != length:
raise newAsyncStreamIncompleteError()
else:
if isNil(wstream.writerLoop):
await write(wstream.wsource, sbytes, msglen)
else:
var item = WriteItem(kind: Sequence)
if not isLiteral(sbytes):
@ -625,6 +649,9 @@ proc write*(wstream: AsyncStreamWriter, sbytes: string,
raise newAsyncStreamWriteError(resFut.error)
if resFut.read() != length:
raise newAsyncStreamIncompleteError()
else:
if isNil(wstream.writerLoop):
await write(wstream.wsource, sbytes, msglen)
else:
var item = WriteItem(kind: String)
if not isLiteral(sbytes):
@ -644,6 +671,9 @@ proc finish*(wstream: AsyncStreamWriter) {.async.} =
raise newAsyncStreamIncorrectError("Incorrect stream state")
if not isNil(wstream.wsource):
if isNil(wstream.writerLoop):
await wstream.wsource.finish()
else:
var item = WriteItem(kind: Pointer)
item.size = 0
item.future = newFuture[void]("async.stream.finish")
@ -684,12 +714,12 @@ proc close*(rw: AsyncStreamRW) =
untrackAsyncStreamWriter(rw)
when rw is AsyncStreamReader:
if isNil(rw.rsource):
if isNil(rw.rsource) or isNil(rw.readerLoop):
callSoon(continuation)
else:
rw.exevent.fire()
elif rw is AsyncStreamWriter:
if isNil(rw.wsource):
if isNil(rw.wsource) or isNil(rw.writerLoop):
callSoon(continuation)
else:
rw.exevent.fire()
@ -787,6 +817,27 @@ proc init*[T](child: AsyncStreamWriter, tsource: StreamTransport,
trackAsyncStreamWriter(child)
child.startWriter()
proc init*(child, wsource: AsyncStreamWriter) =
## Initialize newly allocated object ``child`` with AsyncStreamWriter
## parameters.
child.writerLoop = nil
child.wsource = wsource
child.tsource = wsource.tsource
trackAsyncStreamWriter(child)
child.startWriter()
proc init*[T](child, wsource: AsyncStreamWriter, udata: ref T) =
## Initialize newly allocated object ``child`` with AsyncStreamWriter
## parameters.
child.writerLoop = nil
child.wsource = wsource
child.tsource = wsource.tsource
if not isNil(udata):
GC_ref(udata)
child.udata = cast[pointer](udata)
trackAsyncStreamWriter(child)
child.startWriter()
proc init*(child: AsyncStreamReader, tsource: StreamTransport) =
## Initialize newly allocated object ``child`` with AsyncStreamReader
## parameters.
@ -809,6 +860,27 @@ proc init*[T](child: AsyncStreamReader, tsource: StreamTransport,
trackAsyncStreamReader(child)
child.startReader()
proc init*(child, rsource: AsyncStreamReader) =
## Initialize newly allocated object ``child`` with AsyncStreamReader
## parameters.
child.readerLoop = nil
child.rsource = rsource
child.tsource = rsource.tsource
trackAsyncStreamReader(child)
child.startReader()
proc init*[T](child, rsource: AsyncStreamReader, udata: ref T) =
## Initialize newly allocated object ``child`` with AsyncStreamReader
## parameters.
child.readerLoop = nil
child.rsource = rsource
child.tsource = rsource.tsource
if not isNil(udata):
GC_ref(udata)
child.udata = cast[pointer](udata)
trackAsyncStreamReader(child)
child.startReader()
proc newAsyncStreamReader*[T](rsource: AsyncStreamReader,
loop: StreamReaderLoop,
bufferSize = AsyncStreamDefaultBufferSize,
@ -899,6 +971,34 @@ proc newAsyncStreamWriter*(tsource: StreamTransport): AsyncStreamWriter =
result = new AsyncStreamWriter
result.init(tsource)
proc newAsyncStreamWriter*[T](wsource: AsyncStreamWriter,
udata: ref T): AsyncStreamWriter =
## Create copy of AsyncStreamWriter object ``wsource``.
##
## ``udata`` - user object which will be associated with new AsyncStreamWriter
## object.
result = new AsyncStreamWriter
result.init(wsource, udata)
proc newAsyncStreamWriter*(wsource: AsyncStreamWriter): AsyncStreamWriter =
## Create copy of AsyncStreamWriter object ``wsource``.
result = new AsyncStreamWriter
result.init(wsource)
proc newAsyncStreamReader*[T](rsource: AsyncStreamWriter,
udata: ref T): AsyncStreamWriter =
## Create copy of AsyncStreamReader object ``rsource``.
##
## ``udata`` - user object which will be associated with new AsyncStreamReader
## object.
result = new AsyncStreamReader
result.init(rsource, udata)
proc newAsyncStreamReader*(rsource: AsyncStreamReader): AsyncStreamReader =
## Create copy of AsyncStreamReader object ``rsource``.
result = new AsyncStreamReader
result.init(rsource)
proc getUserData*[T](rw: AsyncStreamRW): T {.inline.} =
## Obtain user data associated with AsyncStreamReader or AsyncStreamWriter
## object ``rw``.