about summary refs log tree commit diff stats
path: root/src/io/bufwriter.nim
diff options
context:
space:
mode:
Diffstat (limited to 'src/io/bufwriter.nim')
-rw-r--r--src/io/bufwriter.nim83
1 files changed, 43 insertions, 40 deletions
diff --git a/src/io/bufwriter.nim b/src/io/bufwriter.nim
index 20ef1f4c..fd3c12a8 100644
--- a/src/io/bufwriter.nim
+++ b/src/io/bufwriter.nim
@@ -6,6 +6,7 @@ import std/sets
 import std/tables
 
 import io/dynstream
+import io/socketstream
 import types/blob
 import types/color
 import types/formdata
@@ -17,7 +18,7 @@ type BufferedWriter* = object
   buffer: ptr UncheckedArray[uint8]
   bufSize: int
   bufLen: int
-  writeLen: bool
+  sendAux: seq[FileHandle]
 
 {.warning[Deprecated]: off.}:
   proc `=destroy`(writer: var BufferedWriter) =
@@ -25,26 +26,42 @@ type BufferedWriter* = object
       dealloc(writer.buffer)
       writer.buffer = nil
 
-proc initWriter*(stream: DynStream; sizeInit = 64; writeLen = false):
+proc swrite*(writer: var BufferedWriter; n: SomeNumber)
+proc swrite*[T](writer: var BufferedWriter; s: set[T])
+proc swrite*[T: enum](writer: var BufferedWriter; x: T)
+proc swrite*(writer: var BufferedWriter; s: string)
+proc swrite*(writer: var BufferedWriter; b: bool)
+proc swrite*(writer: var BufferedWriter; url: URL)
+proc swrite*(writer: var BufferedWriter; tup: tuple)
+proc swrite*[I, T](writer: var BufferedWriter; a: array[I, T])
+proc swrite*(writer: var BufferedWriter; s: seq)
+proc swrite*[U, V](writer: var BufferedWriter; t: Table[U, V])
+proc swrite*(writer: var BufferedWriter; obj: object)
+proc swrite*(writer: var BufferedWriter; obj: ref object)
+proc swrite*(writer: var BufferedWriter; part: FormDataEntry)
+proc swrite*(writer: var BufferedWriter; blob: Blob)
+proc swrite*[T](writer: var BufferedWriter; o: Option[T])
+proc swrite*[T, E](writer: var BufferedWriter; o: Result[T, E])
+proc swrite*(writer: var BufferedWriter; c: ARGBColor) {.inline.}
+
+const InitLen = sizeof(int) * 2
+const SizeInit = max(64, InitLen)
+proc initWriter*(stream: DynStream):
     BufferedWriter =
-  var w = BufferedWriter(
+  return BufferedWriter(
     stream: stream,
-    buffer: cast[ptr UncheckedArray[uint8]](alloc(sizeInit)),
-    bufSize: sizeInit,
-    bufLen: 0,
-    writeLen: writeLen
+    buffer: cast[ptr UncheckedArray[uint8]](alloc(SizeInit)),
+    bufSize: SizeInit,
+    bufLen: InitLen
   )
-  if writeLen: # add space for `len'
-    w.bufLen += sizeof(w.bufLen)
-    assert w.bufLen < sizeInit
-  return w
 
 proc flush*(writer: var BufferedWriter) =
-  if writer.writeLen:
-    # subtract the length field's size
-    var realLen = writer.bufLen - sizeof(writer.bufLen)
-    copyMem(writer.buffer, addr realLen, sizeof(writer.bufLen))
+  # subtract the length field's size
+  let len = [writer.bufLen - InitLen, writer.sendAux.len]
+  copyMem(writer.buffer, unsafeAddr len[0], sizeof(len))
   writer.stream.sendDataLoop(writer.buffer, writer.bufLen)
+  for i in countdown(writer.sendAux.high, 0):
+    SocketStream(writer.stream).sendFileHandle(writer.sendAux[i])
   writer.bufLen = 0
   writer.stream.sflush()
 
@@ -53,32 +70,15 @@ proc deinit*(writer: var BufferedWriter) =
   writer.buffer = nil
   writer.bufSize = 0
   writer.bufLen = 0
+  writer.sendAux.setLen(0)
 
 template withPacketWriter*(stream: DynStream; w, body: untyped) =
   block:
-    var w = stream.initWriter(writeLen = true)
+    var w = stream.initWriter()
     body
     w.flush()
     w.deinit()
 
-proc swrite*(writer: var BufferedWriter; n: SomeNumber)
-proc swrite*[T](writer: var BufferedWriter; s: set[T])
-proc swrite*[T: enum](writer: var BufferedWriter; x: T)
-proc swrite*(writer: var BufferedWriter; s: string)
-proc swrite*(writer: var BufferedWriter; b: bool)
-proc swrite*(writer: var BufferedWriter; url: URL)
-proc swrite*(writer: var BufferedWriter; tup: tuple)
-proc swrite*[I, T](writer: var BufferedWriter; a: array[I, T])
-proc swrite*(writer: var BufferedWriter; s: seq)
-proc swrite*[U, V](writer: var BufferedWriter; t: Table[U, V])
-proc swrite*(writer: var BufferedWriter; obj: object)
-proc swrite*(writer: var BufferedWriter; obj: ref object)
-proc swrite*(writer: var BufferedWriter; part: FormDataEntry)
-proc swrite*(writer: var BufferedWriter; blob: Blob)
-proc swrite*[T](writer: var BufferedWriter; o: Option[T])
-proc swrite*[T, E](writer: var BufferedWriter; o: Result[T, E])
-proc swrite*(writer: var BufferedWriter; c: ARGBColor) {.inline.}
-
 proc writeData(writer: var BufferedWriter; buffer: pointer; len: int) =
   let targetLen = writer.bufLen + len
   let missing = targetLen - writer.bufSize
@@ -161,12 +161,15 @@ proc swrite*(writer: var BufferedWriter; part: FormDataEntry) =
 
 #TODO clean up this mess
 proc swrite*(writer: var BufferedWriter; blob: Blob) =
-  writer.swrite(blob.isfile)
-  if blob.isfile:
-    writer.swrite(WebFile(blob).path)
-  else:
-    writer.swrite(blob.ctype)
-    writer.swrite(blob.size)
+  if blob.fd.isSome:
+    writer.sendAux.add(blob.fd.get)
+  writer.swrite(blob of WebFile)
+  if blob of WebFile:
+    writer.swrite(WebFile(blob).name)
+  writer.swrite(blob.fd.isSome)
+  writer.swrite(blob.ctype)
+  writer.swrite(blob.size)
+  if blob.size > 0:
     writer.writeData(blob.buffer, int(blob.size))
 
 proc swrite*[T](writer: var BufferedWriter; o: Option[T]) =