about summary refs log tree commit diff stats
path: root/src/io
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2024-03-12 14:09:53 +0100
committerbptato <nincsnevem662@gmail.com>2024-03-12 14:09:53 +0100
commit0cc8f357d8f44fcfccd141c078d34ed4530fec5b (patch)
treed07478d4895e9ae008d4d0cba704db3f6bd4ecbf /src/io
parent2ac31dd859c84697d108c88dd1b22b5ffa5beb95 (diff)
downloadchawan-0cc8f357d8f44fcfccd141c078d34ed4530fec5b.tar.gz
io: add dynstream
a new abstraction that we derive posixstream from; hopefully with time
we can get rid of std/streams
Diffstat (limited to 'src/io')
-rw-r--r--src/io/bufstream.nim4
-rw-r--r--src/io/dynstream.nim82
-rw-r--r--src/io/posixstream.nim60
-rw-r--r--src/io/socketstream.nim1
4 files changed, 92 insertions, 55 deletions
diff --git a/src/io/bufstream.nim b/src/io/bufstream.nim
index eb9d6d6b..0558b61c 100644
--- a/src/io/bufstream.nim
+++ b/src/io/bufstream.nim
@@ -1,7 +1,8 @@
+import io/dynstream
 import io/posixstream
 
 type
-  BufStream* = ref object of PosixStream
+  BufStream* = ref object of DynStream
     source*: PosixStream
     registerFun: proc(fd: int)
     registered: bool
@@ -46,7 +47,6 @@ proc flushWrite*(s: BufStream): bool =
 
 proc newBufStream*(ps: PosixStream, registerFun: proc(fd: int)): BufStream =
   result = BufStream(
-    fd: ps.fd,
     source: ps,
     blocking: ps.blocking,
     registerFun: registerFun
diff --git a/src/io/dynstream.nim b/src/io/dynstream.nim
new file mode 100644
index 00000000..d4c7760f
--- /dev/null
+++ b/src/io/dynstream.nim
@@ -0,0 +1,82 @@
+import std/streams
+
+type
+  DynStream* = ref object of Stream #TODO should be of RootObj
+    isend*: bool
+    blocking*: bool #TODO move to posixstream
+
+# Semantics of this function are those of POSIX read(2): that is, it may return
+# a result that is lower than `len`, and that does not mean the stream is
+# finished.
+# isend must be set by implementations when the end of the stream is reached.
+# An exception should be raised if recvData is called with the 'isend' flag set
+# to true.
+method recvData*(s: DynStream; buffer: pointer; len: int): int {.base.} =
+  assert false
+
+# See above, but with write(2)
+method sendData*(s: DynStream; buffer: pointer; len: int): int {.base.} =
+  assert false
+
+method seek*(s: DynStream; off: int) {.base.} =
+  assert false
+
+method sclose*(s: DynStream) {.base.} =
+  assert false
+
+proc recvData*(s: DynStream; buffer: var openArray[uint8]): int {.inline.} =
+  return s.recvData(addr buffer[0], buffer.len)
+
+proc recvData*(s: DynStream; buffer: var openArray[char]): int {.inline.} =
+  return s.recvData(addr buffer[0], buffer.len)
+
+proc sendData*(s: DynStream; buffer: openArray[char]): int {.inline.} =
+  return s.sendData(unsafeAddr buffer[0], buffer.len)
+
+proc sendData*(s: DynStream; buffer: openArray[uint8]): int {.inline.} =
+  return s.sendData(unsafeAddr buffer[0], buffer.len)
+
+proc dsClose(s: Stream) =
+  DynStream(s).sclose()
+
+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
+  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':
+      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
diff --git a/src/io/posixstream.nim b/src/io/posixstream.nim
index dfb6f85b..baf3238c 100644
--- a/src/io/posixstream.nim
+++ b/src/io/posixstream.nim
@@ -1,12 +1,11 @@
 # stdlib file handling is broken, so we use this instead of FileStream.
 import std/posix
-import std/streams
+
+import io/dynstream
 
 type
-  PosixStream* = ref object of Stream
+  PosixStream* = ref object of DynStream
     fd*: cint
-    isend*: bool
-    blocking*: bool
 
   ErrorAgain* = object of IOError
   ErrorBadFD* = object of IOError
@@ -34,7 +33,7 @@ proc raisePosixIOError*() =
   else:
     raise newException(IOError, $strerror(errno))
 
-method recvData*(s: PosixStream, buffer: pointer, len: int): int {.base.} =
+method recvData*(s: PosixStream, buffer: pointer, len: int): int =
   let n = read(s.fd, buffer, len)
   if n < 0:
     raisePosixIOError()
@@ -50,7 +49,7 @@ proc recvData*(s: PosixStream, buffer: var openArray[uint8]): int {.inline.} =
 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 {.base.} =
+method sendData*(s: PosixStream, buffer: pointer, len: int): int =
   let n = write(s.fd, buffer, len)
   if n < 0:
     raisePosixIOError()
@@ -70,57 +69,12 @@ method setBlocking*(s: PosixStream, blocking: bool) {.base.} =
   else:
     discard fcntl(s.fd, F_SETFL, ofl or O_NONBLOCK)
 
-method seek*(s: PosixStream; off: int) {.base.} =
+method seek*(s: PosixStream; off: int) =
   discard lseek(s.fd, Off(off), SEEK_SET)
 
-method sclose*(s: PosixStream) {.base.} =
+method sclose*(s: PosixStream) =
   discard close(s.fd)
 
-proc psClose(s: Stream) =
-  PosixStream(s).sclose()
-
-proc psReadData(s: Stream, buffer: pointer, len: int): int =
-  let s = PosixStream(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 psWriteData(s: Stream, buffer: pointer, len: int) =
-  let s = PosixStream(s)
-  assert len != 0 and s.blocking
-  discard s.sendData(buffer, len)
-
-proc psReadLine(s: Stream, line: var string): bool =
-  let s = PosixStream(s)
-  assert s.blocking
-  line = ""
-  var c: char
-  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':
-      break
-    line &= c
-  true
-
-proc psAtEnd(s: Stream): bool =
-  return PosixStream(s).isend
-
-proc addStreamIface*(ps: PosixStream) =
-  ps.closeImpl = cast[typeof(ps.closeImpl)](psClose)
-  ps.readDataImpl = cast[typeof(ps.readDataImpl)](psReadData)
-  ps.writeDataImpl = cast[typeof(ps.writeDataImpl)](psWriteData)
-  ps.readLineImpl = cast[typeof(ps.readLineImpl)](psReadLine)
-  ps.atEndImpl = psAtEnd
-
 proc newPosixStream*(fd: FileHandle): PosixStream =
   let ps = PosixStream(fd: fd, blocking: true)
   ps.addStreamIface()
diff --git a/src/io/socketstream.nim b/src/io/socketstream.nim
index 168b7a4f..e02108ce 100644
--- a/src/io/socketstream.nim
+++ b/src/io/socketstream.nim
@@ -2,6 +2,7 @@ import std/nativesockets
 import std/net
 import std/os
 
+import io/dynstream
 import io/posixstream
 import io/serversocket