diff options
author | bptato <nincsnevem662@gmail.com> | 2024-03-24 14:12:27 +0100 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2024-03-24 14:21:01 +0100 |
commit | fb21b1e4f0ee0e55e9556bf1f399d00d5eae26e4 (patch) | |
tree | c532aa98ee6bedf19b840f4ea0c7360a42407fbf /src/io | |
parent | b27deb7672c53e3ee59f91b7091e83ab28a8318d (diff) | |
download | chawan-fb21b1e4f0ee0e55e9556bf1f399d00d5eae26e4.tar.gz |
io: derive DynStream from RootObj (not Stream)
This way they are no longer compatible, but we no longer need them to be compatible anyway. (This also forces us to throw out the old serialize module, and use packet writers everywhere.)
Diffstat (limited to 'src/io')
-rw-r--r-- | src/io/bufstream.nim | 3 | ||||
-rw-r--r-- | src/io/bufwriter.nim | 10 | ||||
-rw-r--r-- | src/io/dynstream.nim | 70 | ||||
-rw-r--r-- | src/io/filestream.nim | 34 | ||||
-rw-r--r-- | src/io/posixstream.nim | 17 | ||||
-rw-r--r-- | src/io/serialize.nim | 234 | ||||
-rw-r--r-- | src/io/socketstream.nim | 6 |
7 files changed, 66 insertions, 308 deletions
diff --git a/src/io/bufstream.nim b/src/io/bufstream.nim index 0558b61c..118b81e5 100644 --- a/src/io/bufstream.nim +++ b/src/io/bufstream.nim @@ -46,9 +46,8 @@ proc flushWrite*(s: BufStream): bool = return false proc newBufStream*(ps: PosixStream, registerFun: proc(fd: int)): BufStream = - result = BufStream( + return BufStream( source: ps, blocking: ps.blocking, registerFun: registerFun ) - result.addStreamIface() diff --git a/src/io/bufwriter.nim b/src/io/bufwriter.nim index cbee8b5b..75da4190 100644 --- a/src/io/bufwriter.nim +++ b/src/io/bufwriter.nim @@ -1,4 +1,5 @@ -# Write data to streams. +# Write data to streams in packets. +# Each packet is prefixed with its length as a pointer-sized integer. import std/options import std/sets @@ -53,13 +54,6 @@ proc deinit*(writer: var BufferedWriter) = writer.bufSize = 0 writer.bufLen = 0 -template withWriter*(stream: DynStream; w, body: untyped) = - block: - var w = stream.initWriter() - body - w.flush() - w.deinit() - template withPacketWriter*(stream: DynStream; w, body: untyped) = block: var w = stream.initWriter(writeLen = true) diff --git a/src/io/dynstream.nim b/src/io/dynstream.nim index 10db4c64..1b0f8807 100644 --- a/src/io/dynstream.nim +++ b/src/io/dynstream.nim @@ -1,7 +1,5 @@ -import std/streams - type - DynStream* = ref object of Stream #TODO should be of RootObj + DynStream* = ref object of RootObj isend*: bool blocking*: bool #TODO move to posixstream @@ -46,6 +44,19 @@ proc sendDataLoop*(s: DynStream; buffer: pointer; len: int) = if n == len: break +proc sendDataLoop*(s: DynStream; buffer: openArray[char]) {.inline.} = + s.sendDataLoop(unsafeAddr buffer[0], buffer.len) + +proc write*(s: DynStream; buffer: openArray[char]) {.inline.} = + s.sendDataLoop(buffer) + +proc write*(s: DynStream; c: char) {.inline.} = + s.sendDataLoop(unsafeAddr c, 1) + +proc sreadChar*(s: DynStream): char = + let n = s.recvData(addr result, 1) + assert n == 1 + proc recvDataLoop*(s: DynStream; buffer: pointer; len: int) = var n = 0 while true: @@ -53,47 +64,18 @@ proc recvDataLoop*(s: DynStream; buffer: pointer; len: int) = if n == len: break -proc dsClose(s: Stream) = - DynStream(s).sclose() +proc recvDataLoop*(s: DynStream; buffer: var openArray[uint8]) {.inline.} = + s.recvDataLoop(addr buffer[0], buffer.len) -proc dsReadData(s: Stream, buffer: pointer, len: int): int = - let s = DynStream(s) - assert len != 0 and s.blocking - result = 0 - while result < len: - let p = addr cast[ptr UncheckedArray[uint8]](buffer)[result] - let n = s.recvData(p, len - result) - if n == 0: - break - result += n - -proc dsWriteData(s: Stream, buffer: pointer, len: int) = - let s = DynStream(s) - assert len != 0 and s.blocking - discard s.sendData(buffer, len) - -proc dsReadLine(s: Stream, line: var string): bool = - let s = DynStream(s) - assert s.blocking - line = "" - var c: char +proc recvAll*(s: DynStream): string = + var buffer = newString(4096) + var idx = 0 while true: - if s.recvData(addr c, 1) == 0: - return false - if c == '\r': - if s.recvData(addr c, 1) == 0: - return false - if c == '\n': + let n = s.recvData(addr buffer[idx], buffer.len - idx) + if n == 0: break - line &= c - true - -proc dsAtEnd(s: Stream): bool = - return DynStream(s).isend - -proc addStreamIface*(s: DynStream) = - s.closeImpl = cast[typeof(s.closeImpl)](dsClose) - s.readDataImpl = cast[typeof(s.readDataImpl)](dsReadData) - s.writeDataImpl = cast[typeof(s.writeDataImpl)](dsWriteData) - s.readLineImpl = cast[typeof(s.readLineImpl)](dsReadLine) - s.atEndImpl = dsAtEnd + idx += n + if idx == buffer.len: + buffer.setLen(buffer.len + 4096) + buffer.setLen(idx) + return buffer diff --git a/src/io/filestream.nim b/src/io/filestream.nim new file mode 100644 index 00000000..b1b3a296 --- /dev/null +++ b/src/io/filestream.nim @@ -0,0 +1,34 @@ +import io/dynstream + +type + DynFileStream* = ref object of DynStream + file*: File + +method recvData*(s: DynFileStream; buffer: pointer; len: int): int = + let n = s.file.readBuffer(buffer, len) + if n == 0: + if unlikely(s.isend): + raise newException(EOFError, "eof") + s.isend = true + return n + +method sendData*(s: DynFileStream; buffer: pointer; len: int): int = + return s.file.writeBuffer(buffer, len) + +method seek*(s: DynFileStream; off: int) = + s.file.setFilePos(int64(off)) + +method sclose*(s: DynFileStream) = + s.file.close() + +method sflush*(s: DynFileStream) = + s.file.flushFile() + +proc newDynFileStream*(file: File): DynFileStream = + return DynFileStream(file: file, blocking: true) + +proc newDynFileStream*(path: string): DynFileStream = + var file: File + if file.open(path): + return newDynFileStream(path) + return nil diff --git a/src/io/posixstream.nim b/src/io/posixstream.nim index 0b06c572..bdae9d50 100644 --- a/src/io/posixstream.nim +++ b/src/io/posixstream.nim @@ -1,4 +1,3 @@ -# stdlib file handling is broken, so we use this instead of FileStream. import std/posix import io/dynstream @@ -53,24 +52,12 @@ proc sreadChar*(s: PosixStream): char = s.isend = true assert n == 1 -proc recvData*(s: PosixStream, buffer: var openArray[uint8]): int {.inline.} = - return s.recvData(addr buffer[0], buffer.len) - -proc recvData*(s: PosixStream, buffer: var openArray[char]): int {.inline.} = - return s.recvData(addr buffer[0], buffer.len) - method sendData*(s: PosixStream, buffer: pointer, len: int): int = let n = write(s.fd, buffer, len) if n < 0: raisePosixIOError() return n -proc sendData*(s: PosixStream, buffer: openArray[char]): int {.inline.} = - return s.sendData(unsafeAddr buffer[0], buffer.len) - -proc sendData*(s: PosixStream, buffer: openArray[uint8]): int {.inline.} = - return s.sendData(unsafeAddr buffer[0], buffer.len) - method setBlocking*(s: PosixStream, blocking: bool) {.base.} = s.blocking = blocking let ofl = fcntl(s.fd, F_GETFL, 0) @@ -87,9 +74,7 @@ method sclose*(s: PosixStream) = discard close(s.fd) proc newPosixStream*(fd: FileHandle): PosixStream = - let ps = PosixStream(fd: fd, blocking: true) - ps.addStreamIface() - return ps + return PosixStream(fd: fd, blocking: true) proc newPosixStream*(path: string, flags, mode: cint): PosixStream = let fd = open(cstring(path), flags, mode) diff --git a/src/io/serialize.nim b/src/io/serialize.nim deleted file mode 100644 index 0b54bea3..00000000 --- a/src/io/serialize.nim +++ /dev/null @@ -1,234 +0,0 @@ -# Write data to streams. - -import std/options -import std/sets -import std/streams -import std/tables - -import types/blob -import types/formdata -import types/url -import types/opt - -proc sread*(stream: Stream, n: var SomeNumber) -func slen*(n: SomeNumber): int - -proc sread*[T](stream: Stream, s: var set[T]) -func slen*[T](s: set[T]): int - -proc sread*[T: enum](stream: Stream, x: var T) -func slen*[T: enum](x: T): int - -proc sread*(stream: Stream, s: var string) -func slen*(s: string): int - -proc sread*(stream: Stream, b: var bool) -func slen*(b: bool): int - -func slen*(url: URL): int - -func slen*(tup: tuple): int - -proc sread*[I, T](stream: Stream, a: var array[I, T]) -func slen*[I, T](a: array[I, T]): int - -proc sread*(stream: Stream, s: var seq) -func slen*(s: seq): int - -proc sread*[U, V](stream: Stream, t: var Table[U, V]) -func slen*[U, V](t: Table[U, V]): int - -proc sread*(stream: Stream, obj: var object) -func slen*(obj: object): int - -proc sread*(stream: Stream, obj: var ref object) -func slen*(obj: ref object): int - -func slen*(part: FormDataEntry): int - -func slen*(blob: Blob): int - -proc sread*[T](stream: Stream, o: var Option[T]) -func slen*[T](o: Option[T]): int - -proc sread*[T, E](stream: Stream, o: var Result[T, E]) -func slen*[T, E](o: Result[T, E]): int - -proc sread*(stream: Stream, n: var SomeNumber) = - if stream.readData(addr n, sizeof(n)) < sizeof(n): - raise newException(EOFError, "eof") - -func slen*(n: SomeNumber): int = - return sizeof(n) - -proc sread*[T: enum](stream: Stream, x: var T) = - var i: int - stream.sread(i) - x = cast[T](i) - -func slen*[T: enum](x: T): int = - return sizeof(int) - -proc sread*[T](stream: Stream, s: var set[T]) = - var len: int - stream.sread(len) - for i in 0 ..< len: - var x: T - stream.sread(x) - s.incl(x) - -func slen*[T](s: set[T]): int = - result = slen(s.card) - for x in s: - result += slen(x) - -proc sread*(stream: Stream, s: var string) = - var len: int - stream.sread(len) - if len > 0: - s = newString(len) - prepareMutation(s) - if stream.readData(addr s[0], len) < len: - raise newException(EOFError, "eof") - else: - s = "" - -func slen*(s: string): int = - slen(s.len) + s.len - -proc sread*(stream: Stream, b: var bool) = - var n: uint8 - stream.sread(n) - if n == 1u8: - b = true - else: - assert n == 0u8 - b = false - -func slen*(b: bool): int = - return sizeof(uint8) - -func slen*(url: URL): int = - if url == nil: - return slen("") - return slen(url.serialize()) - -func slen*(tup: tuple): int = - for f in tup.fields: - result += slen(f) - -proc sread*[I, T](stream: Stream; a: var array[I, T]) = - for x in a.mitems: - stream.sread(x) - -func slen*[I, T](a: array[I, T]): int = - for x in a: - result += slen(x) - -proc sread*(stream: Stream, s: var seq) = - var len: int - stream.sread(len) - s.setLen(len) - for x in s.mitems: - stream.sread(x) - -func slen*(s: seq): int = - result = slen(s.len) - for x in s: - result += slen(x) - -proc sread*[U, V](stream: Stream, t: var Table[U, V]) = - var len: int - stream.sread(len) - for i in 0..<len: - var k: U - stream.sread(k) - var v: V - stream.sread(v) - t[k] = v - -func slen*[U, V](t: Table[U, V]): int = - result = slen(t.len) - for k, v in t: - result += slen(k) - result += slen(v) - -proc sread*(stream: Stream, obj: var object) = - for f in obj.fields: - stream.sread(f) - -func slen*(obj: object): int = - for f in obj.fields: - result += slen(f) - -proc sread*(stream: Stream, obj: var ref object) = - var n: bool - stream.sread(n) - if n: - new(obj) - stream.sread(obj[]) - -func slen*(obj: ref object): int = - result = slen(obj != nil) - if obj != nil: - result += slen(obj[]) - -func slen*(part: FormDataEntry): int = - result += slen(part.isstr) - result += slen(part.name) - result += slen(part.filename) - if part.isstr: - result += slen(part.svalue) - else: - result += slen(part.value) - -func slen*(blob: Blob): int = - result += slen(blob.isfile) - if blob.isfile: - result = slen(WebFile(blob).path) - else: - result += slen(blob.ctype) - result += slen(blob.size) - result += int(blob.size) #TODO ?? - -proc sread*[T](stream: Stream, o: var Option[T]) = - var x: bool - stream.sread(x) - if x: - var m: T - stream.sread(m) - o = some(m) - else: - o = none(T) - -func slen*[T](o: Option[T]): int = - result = slen(o.isSome) - if o.isSome: - result += slen(o.get) - -proc sread*[T, E](stream: Stream, o: var Result[T, E]) = - var x: bool - stream.sread(x) - if x: - when not (T is void): - var m: T - stream.sread(m) - o.ok(m) - else: - o.ok() - else: - when not (E is void): - var e: E - stream.sread(e) - o.err(e) - else: - o.err() - -func slen*[T, E](o: Result[T, E]): int = - result = slen(o.isSome) - if o.isSome: - when not (T is void): - result += slen(o.get) - else: - when not (E is void): - result += slen(o.error) diff --git a/src/io/socketstream.nim b/src/io/socketstream.nim index 78e7fb3e..3c8e6fa6 100644 --- a/src/io/socketstream.nim +++ b/src/io/socketstream.nim @@ -69,12 +69,11 @@ proc connectSocketStream*(path: string; blocking = true): SocketStream = if connect_unix_from_c(cint(sock.getFd()), cstring(path), cint(path.len)) != 0: raiseOSError(osLastError()) - result = SocketStream( + return SocketStream( source: sock, fd: cint(sock.getFd()), blocking: blocking ) - result.addStreamIface() proc connectSocketStream*(pid: int; blocking = true): SocketStream = @@ -88,9 +87,8 @@ proc acceptSocketStream*(ssock: ServerSocket, blocking = true): SocketStream = ssock.sock.accept(sock, inheritable = true) if not blocking: sock.getFd().setBlocking(false) - result = SocketStream( + return SocketStream( blocking: blocking, source: sock, fd: cint(sock.getFd()) ) - result.addStreamIface() |