about summary refs log blame commit diff stats
path: root/src/io/bufreader.nim
blob: bc448edf1f1857fba1e4414921d8548cea7d219a (plain) (tree)
1
2
3
4
5
6
7
8
9



                  
                 
                   
                     
                 
                  






                             
                                                      
















                                                                  
                                                                    

                                                           
 




















                                                                       































































                                                                      
                                                                   


































                                                                  











                                             
                                 
                                                
                        
                                 



























                                                                    
 
                                                           
                         
























                                                             
                    
                    

                           
                         
                             


                        


                              
     
import std/options
import std/sets
import std/tables

import img/bitmap
import io/dynstream
import loader/request
import types/blob
import types/color
import types/formdata
import types/opt
import types/url

type BufferedReader* = object
  buffer: seq[uint8]
  bufIdx: int
  recvAux: seq[FileHandle] #TODO assert on unused ones

proc sread*(reader: var BufferedReader; n: var SomeNumber)
proc sread*[T](reader: var BufferedReader; s: var set[T])
proc sread*[T: enum](reader: var BufferedReader; x: var T)
proc sread*(reader: var BufferedReader; s: var string)
proc sread*(reader: var BufferedReader; b: var bool)
proc sread*(reader: var BufferedReader; url: var URL)
proc sread*(reader: var BufferedReader; tup: var tuple)
proc sread*[I, T](reader: var BufferedReader; a: var array[I, T])
proc sread*(reader: var BufferedReader; s: var seq)
proc sread*[U, V](reader: var BufferedReader; t: var Table[U, V])
proc sread*(reader: var BufferedReader; obj: var object)
proc sread*(reader: var BufferedReader; obj: var ref object)
proc sread*(reader: var BufferedReader; part: var FormDataEntry)
proc sread*(reader: var BufferedReader; blob: var Blob)
proc sread*[T](reader: var BufferedReader; o: var Option[T])
proc sread*[T, E](reader: var BufferedReader; o: var Result[T, E])
proc sread*(reader: var BufferedReader; c: var ARGBColor) {.inline.}
proc sread*(reader: var BufferedReader; o: var RequestBody)
proc sread*(reader: var BufferedReader; bmp: var Bitmap)

proc initReader*(stream: DynStream; len, auxLen: int): BufferedReader =
  assert len != 0
  var reader = BufferedReader(
    buffer: newSeqUninitialized[uint8](len),
    bufIdx: 0
  )
  stream.recvDataLoop(reader.buffer)
  for i in 0 ..< auxLen:
    reader.recvAux.add(SocketStream(stream).recvFileHandle())
  return reader

proc initPacketReader*(stream: DynStream): BufferedReader =
  var len: array[2, int]
  stream.recvDataLoop(addr len[0], sizeof(len))
  return stream.initReader(len[0], len[1])

template withPacketReader*(stream: DynStream; r, body: untyped) =
  block:
    var r = stream.initPacketReader()
    body

proc readData(reader: var BufferedReader; buffer: pointer; len: int) =
  assert reader.bufIdx + len <= reader.buffer.len
  copyMem(buffer, addr reader.buffer[reader.bufIdx], len)
  reader.bufIdx += len

proc sread*(reader: var BufferedReader; n: var SomeNumber) =
  reader.readData(addr n, sizeof(n))

proc sread*[T: enum](reader: var BufferedReader; x: var T) =
  var i: int
  reader.sread(i)
  x = cast[T](i)

proc sread*[T](reader: var BufferedReader; s: var set[T]) =
  var len: int
  reader.sread(len)
  for i in 0 ..< len:
    var x: T
    reader.sread(x)
    s.incl(x)

proc sread*(reader: var BufferedReader; s: var string) =
  var len: int
  reader.sread(len)
  s = newString(len)
  if len > 0:
    reader.readData(addr s[0], len)

proc sread*(reader: var BufferedReader; b: var bool) =
  var n: uint8
  reader.sread(n)
  if n == 1u8:
    b = true
  else:
    assert n == 0u8
    b = false

proc sread*(reader: var BufferedReader; url: var URL) =
  var s: string
  reader.sread(s)
  if s == "":
    url = nil
  else:
    let x = newURL(s)
    if x.isSome:
      url = x.get
    else:
      url = nil

proc sread*(reader: var BufferedReader; tup: var tuple) =
  for f in tup.fields:
    reader.sread(f)

proc sread*[I; T](reader: var BufferedReader; a: var array[I, T]) =
  for x in a.mitems:
    reader.sread(x)

proc sread*(reader: var BufferedReader; s: var seq) =
  var len: int
  reader.sread(len)
  s.setLen(len)
  for x in s.mitems:
    reader.sread(x)

proc sread*[U; V](reader: var BufferedReader; t: var Table[U, V]) =
  var len: int
  reader.sread(len)
  for i in 0..<len:
    var k: U
    reader.sread(k)
    var v: V
    reader.sread(v)
    t[k] = v

proc sread*(reader: var BufferedReader; obj: var object) =
  for f in obj.fields:
    reader.sread(f)

proc sread*(reader: var BufferedReader; obj: var ref object) =
  var n: bool
  reader.sread(n)
  if n:
    new(obj)
    reader.sread(obj[])

proc sread*(reader: var BufferedReader; part: var FormDataEntry) =
  var isstr: bool
  reader.sread(isstr)
  if isstr:
    part = FormDataEntry(isstr: true)
  else:
    part = FormDataEntry(isstr: false)
  reader.sread(part.name)
  reader.sread(part.filename)
  if part.isstr:
    reader.sread(part.svalue)
  else:
    reader.sread(part.value)

proc sread*(reader: var BufferedReader; blob: var Blob) =
  var isWebFile: bool
  reader.sread(isWebFile)
  blob = if isWebFile: WebFile() else: Blob()
  if isWebFile:
    reader.sread(WebFile(blob).name)
  var hasFd: bool
  reader.sread(hasFd)
  if hasFd:
    blob.fd = some(reader.recvAux.pop())
  reader.sread(blob.ctype)
  reader.sread(blob.size)
  if blob.size > 0:
    let buffer = alloc(blob.size)
    reader.readData(blob.buffer, int(blob.size))
    blob.buffer = buffer
    blob.deallocFun = deallocBlob

proc sread*[T](reader: var BufferedReader; o: var Option[T]) =
  var x: bool
  reader.sread(x)
  if x:
    var m: T
    reader.sread(m)
    o = some(m)
  else:
    o = none(T)

proc sread*[T, E](reader: var BufferedReader; o: var Result[T, E]) =
  var x: bool
  reader.sread(x)
  if x:
    when T isnot void:
      var m: T
      reader.sread(m)
      o.ok(m)
    else:
      o.ok()
  else:
    when E isnot void:
      var e: E
      reader.sread(e)
      o.err(e)
    else:
      o.err()

proc sread*(reader: var BufferedReader; c: var ARGBColor) =
  reader.sread(uint32(c))

proc sread*(reader: var BufferedReader; o: var RequestBody) =
  var t: RequestBodyType
  reader.sread(t)
  o = RequestBody(t: t)
  case t
  of rbtNone: discard
  of rbtString: reader.sread(o.s)
  of rbtMultipart: reader.sread(o.multipart)
  of rbtOutput: reader.sread(o.outputId)

proc sread*(reader: var BufferedReader; bmp: var Bitmap) =
  var isImageBitmap: bool
  var width: uint64
  var height: uint64
  reader.sread(isImageBitmap)
  reader.sread(width)
  reader.sread(height)
  if isImageBitmap:
    bmp = ImageBitmap(
      width: width,
      height: height
    )
    reader.sread(bmp.px)
  else:
    var cacheId: int
    var imageId: int
    var contentType: string
    reader.sread(cacheId)
    reader.sread(imageId)
    reader.sread(contentType)
    bmp = NetworkBitmap(
      width: width,
      height: height,
      cacheId: cacheId,
      imageId: imageId,
      contentType: contentType
    )