traitor/streams

Source   Edit  

A basic std/streams like API built using Traitor instead of OOP.

Example:

import traitor/streams
## Static dispatched API
var ss = StringStream(data: "Hello")
assert ss.read(array[5, char]) == "Hello"
ss.setPos(0)
assert ss.read(5) == "Hello"
discard ss.write(", World!")
ss.setPos(0)
assert ss.read(array[13, char]) == "Hello, World!"
ss.setPos(0)
assert ss.read(array[13, char]) == "Hello, World!"

var fs = FileStream.init("/tmp/test.txt", fmReadWrite)
discard fs.write"Hello"
fs.setPos(0)
assert fs.read(array[5, char]) == "Hello"
fs.setPos(0)
assert fs.read(5) == "Hello"
discard fs.write(", World!")
fs.setPos(0)
assert fs.read(array[13, char]) == "Hello, World!"
fs.setPos(0)
assert fs.read(array[13, char]) == "Hello, World!"

## Dynamically dispatched API
var strms = [StringStream().toTrait StreamTrait, FileStream.init("/tmp/test2.txt", fmReadWrite).toTrait StreamTrait]
for strm in strms.mitems:
  discard strm.write "Hello"
  strm.setPos(0)
  assert strm.read(array[5, char]) == "Hello"
  strm.setPos(0)
  assert strm.read(5) == "Hello"
  discard strm.write(", World!")
  strm.setPos(0)
  assert strm.read(array[13, char]) == "Hello, World!"
  strm.setPos(0)
  assert strm.read(array[13, char]) == "Hello, World!"

Types

FileStream = object
  
Source   Edit  
Primitive = concept typeof(P)
    onlyPrimitives(P)
Any type that is onlyPrimitives(T) is true Source   Edit  
PrimitiveAtom = SomeOrdinal or SomeFloat or enum or bool or char or
    PrimitiveBase or
    set
Built in value types that can be copied by memory Source   Edit  
PrimitiveBase = concept pb
    pb.distinctBase is PrimitiveAtom
Source   Edit  
Stream = AnyTraitor[StreamTrait]
Allows static dispatch where possible, but also dynamic dispatch when converted to a Traitor[Stream] Source   Edit  
StreamTrait = distinct tuple[readData: proc (_: var Atom; dest: pointer;
    len: int): int {.nimcall.}, writeData: proc (_: var Atom; toWrite: pointer;
    len: int): int {.nimcall.}, setPos: proc (_: var Atom; pos: int) {.nimcall.},
                             getPos: proc (_: Atom): int {.nimcall.},
                             atEnd: proc (_: Atom): bool {.nimcall.}]
Any stream must match this trait to be used by this API. Source   Edit  
StringStream = object
  data*: string
Source   Edit  

Procs

proc atEnd(fs: var FileStream): bool {....raises: [], tags: [], forbids: [].}
Source   Edit  
proc atEnd(param0: Traitor[StreamTrait]): bool {....raises: [Exception],
    tags: [RootEffect], forbids: [].}
Source   Edit  
proc atEnd(ss: StringStream): bool {....raises: [], tags: [], forbids: [].}
Source   Edit  
proc getPos(fs: var FileStream): int {....raises: [IOError], tags: [], forbids: [].}
Source   Edit  
proc getPos(param0: Traitor[StreamTrait]): int {....raises: [Exception],
    tags: [RootEffect], forbids: [].}
Source   Edit  
proc getPos(ss: var StringStream): int {....raises: [], tags: [], forbids: [].}
Source   Edit  
proc init(_: typedesc[FileStream]; path: string; mode: FileMode = fmRead): FileStream
Source   Edit  
proc onlyPrimitives(val: typedesc[PrimitiveAtom])
All PrimitiveAtoms are safe to stream directly. Source   Edit  
proc onlyPrimitives[Idx, T](val: typedesc[array[Idx, T]])
Procedure to ensure arrays only are made of prototypes Source   Edit  
proc read(strm: var Stream; maxAmount: int): string
Reads upto maxAmount from strm Source   Edit  
proc read(strm: var Stream; T: typedesc[Primitive]): T:type
Reads the exact amount from strm Raises if it fails to read fully Source   Edit  
proc readData(fs: var FileStream; dest: pointer; amount: int): int {.
    ...raises: [IOError], tags: [ReadIOEffect], forbids: [].}
Source   Edit  
proc readData(param0: Traitor[StreamTrait]; param1: pointer; param2: int): int {.
    ...raises: [Exception], tags: [RootEffect], forbids: [].}
Source   Edit  
proc readData(ss: var StringStream; dest: pointer; amount: int): int {.
    ...raises: [], tags: [], forbids: [].}
Source   Edit  
proc setPos(fs: var FileStream; pos: int) {....raises: [IOError], tags: [],
    forbids: [].}
Source   Edit  
proc setPos(param0: Traitor[StreamTrait]; param1: int) {....raises: [Exception],
    tags: [RootEffect], forbids: [].}
Source   Edit  
proc setPos(ss: var StringStream; pos: int) {....raises: [], tags: [], forbids: [].}
Source   Edit  
proc toTrait[T; Constraint: StreamTrait](val`gensym0: sink T;
    traitTyp`gensym0: typedesc[Constraint]): auto
Converts a type to traitType ensuring it implements procedures This creates a ref type and moves val to it Source   Edit  
proc write(strm: var Stream; data: Primitive): int
Writes data to strm Source   Edit  
proc write(strm: var Stream; data: string): int
Overload for string that writes data's data to strm Source   Edit  
proc writeData(fs: var FileStream; data: pointer; amount: int): int {.
    ...raises: [IOError], tags: [WriteIOEffect], forbids: [].}
Source   Edit  
proc writeData(param0: Traitor[StreamTrait]; param1: pointer; param2: int): int {.
    ...raises: [Exception], tags: [RootEffect], forbids: [].}
Source   Edit  
proc writeData(ss: var StringStream; dest: pointer; amount: int): int {.
    ...raises: [], tags: [], forbids: [].}
Source   Edit