[OutputStream] Clean up TODO items unlocked by Nim 1.2; Simplify the public API
This commit is contained in:
parent
8a3cf6778d
commit
62136f8e79
2 changed files with 48 additions and 59 deletions
|
|
@ -1,14 +1,15 @@
|
||||||
import
|
import
|
||||||
deques, stew/[ptrops, strings, ranges/ptr_arith]
|
deques, typetraits,
|
||||||
|
stew/[ptrops, strings, ranges/ptr_arith]
|
||||||
|
|
||||||
type
|
type
|
||||||
OutputPage = object
|
OutputPage = object
|
||||||
buffer: string
|
buffer: string
|
||||||
startOffset: int
|
startOffset: int
|
||||||
|
|
||||||
# somehow casting outputDevice to
|
# We inherit from RootObj because in layered streams
|
||||||
# OutputStreamVar requires RootObj
|
# the stream itself is often used as an `outputDevice`
|
||||||
OutputStream* = object of RootObj
|
OutputStreamObj = object of RootObj
|
||||||
cursor*: WriteCursor
|
cursor*: WriteCursor
|
||||||
pages: Deque[OutputPage]
|
pages: Deque[OutputPage]
|
||||||
endPos: int
|
endPos: int
|
||||||
|
|
@ -19,31 +20,24 @@ type
|
||||||
maxWriteSize*: int
|
maxWriteSize*: int
|
||||||
minWriteSize*: int
|
minWriteSize*: int
|
||||||
|
|
||||||
|
OutputStream* = ref OutputStreamObj
|
||||||
|
OutputStreamVar = OutputStream
|
||||||
|
|
||||||
|
OutputStreamVTable* = object
|
||||||
|
writePage*: proc (s: OutputStream, page: openarray[byte])
|
||||||
|
{.nimcall, gcsafe, raises: [IOError, Defect].}
|
||||||
|
|
||||||
|
flush*: proc (s: OutputStream)
|
||||||
|
{.nimcall, gcsafe, raises: [IOError, Defect].}
|
||||||
|
|
||||||
WriteCursor* = object
|
WriteCursor* = object
|
||||||
head, bufferEnd: ptr byte
|
head, bufferEnd: ptr byte
|
||||||
stream: OutputStreamVar
|
stream: OutputStreamVar
|
||||||
|
|
||||||
FileOutput = ref object of RootObj
|
|
||||||
file: File
|
|
||||||
|
|
||||||
OutputStreamVar* = ref OutputStream
|
|
||||||
|
|
||||||
MemOutputStream* = distinct OutputStreamVar
|
|
||||||
# Writing to a MemOutputStream produces no side-effects
|
|
||||||
|
|
||||||
# Keep this temporary for backward-compatibility
|
|
||||||
DelayedWriteCursor* = WriteCursor
|
|
||||||
VarSizeWriteCursor* = distinct WriteCursor
|
VarSizeWriteCursor* = distinct WriteCursor
|
||||||
|
|
||||||
OutputStreamVTable* = object
|
FileOutput = ref object of RootObj
|
||||||
# TODO - the noSideEffect is temporary here until we switch to Nim 0.20.2
|
file: File
|
||||||
# where noSideEffects overrides may make it possible to implement
|
|
||||||
# the MemOutputStream handling.
|
|
||||||
writePage*: proc (s: OutputStreamVar, page: openarray[byte])
|
|
||||||
{.noSideEffect, nimcall, gcsafe, raises: [IOError, Defect] .}
|
|
||||||
|
|
||||||
flush*: proc (s: OutputStreamVar)
|
|
||||||
{.noSideEffect, nimcall, gcsafe, raises: [IOError, Defect].}
|
|
||||||
|
|
||||||
const
|
const
|
||||||
allocatorMetadata = 0 # TODO: Get this from Nim's allocator.
|
allocatorMetadata = 0 # TODO: Get this from Nim's allocator.
|
||||||
|
|
@ -89,14 +83,11 @@ proc initWithSinglePage*(s: OutputStreamVar,
|
||||||
s.cursor.stream = s
|
s.cursor.stream = s
|
||||||
|
|
||||||
proc init*(T: type OutputStream,
|
proc init*(T: type OutputStream,
|
||||||
pageSize = defaultPageSize): ref OutputStream =
|
pageSize = defaultPageSize): OutputStream =
|
||||||
new result
|
result = OutputStream()
|
||||||
result.initWithSinglePage pageSize, high(int)
|
result.initWithSinglePage pageSize, high(int)
|
||||||
|
|
||||||
when false:
|
let FileStreamVTable = OutputStreamVTable(
|
||||||
# TODO: revisit this when we switch to Nim 0.20.2 and we have working
|
|
||||||
# noSideEffect overrides.
|
|
||||||
let FileStreamVTable = OutputStreamVTable(
|
|
||||||
writePage: proc (s: OutputStreamVar, data: openarray[byte]) {.nimcall, gcsafe.} =
|
writePage: proc (s: OutputStreamVar, data: openarray[byte]) {.nimcall, gcsafe.} =
|
||||||
var output = FileOutput(s.outputDevice)
|
var output = FileOutput(s.outputDevice)
|
||||||
var written = output.file.writeBuffer(unsafeAddr data[0], data.len)
|
var written = output.file.writeBuffer(unsafeAddr data[0], data.len)
|
||||||
|
|
@ -106,19 +97,19 @@ when false:
|
||||||
flush: proc (s: OutputStreamVar) {.nimcall, gcsafe.} =
|
flush: proc (s: OutputStreamVar) {.nimcall, gcsafe.} =
|
||||||
var output = FileOutput(s.outputDevice)
|
var output = FileOutput(s.outputDevice)
|
||||||
flushFile output.file
|
flushFile output.file
|
||||||
)
|
)
|
||||||
|
|
||||||
proc init*(T: type OutputStream,
|
proc init*(T: type OutputStream,
|
||||||
filename: string,
|
filename: string,
|
||||||
pageSize = defaultPageSize): ref OutputStream =
|
pageSize = defaultPageSize): OutputStream =
|
||||||
new result
|
result = OutputStream(
|
||||||
result.outputDevice = FileOutput(file: open(filename, fmWrite))
|
outputDevice: FileOutput(file: open(filename, fmWrite)),
|
||||||
result.vtable = unsafeAddr FileStreamVTable
|
vtable: unsafeAddr FileStreamVTable)
|
||||||
result.initWithSinglePage pageSize, high(int)
|
result.initWithSinglePage pageSize, high(int)
|
||||||
|
|
||||||
proc init*(T: type OutputStream,
|
proc init*(T: type OutputStream,
|
||||||
buffer: pointer, len: int): ref OutputStream =
|
buffer: pointer, len: int): OutputStream =
|
||||||
new result
|
result = OutputStream()
|
||||||
let buffer = cast[ptr byte](buffer)
|
let buffer = cast[ptr byte](buffer)
|
||||||
result.cursor.head = buffer
|
result.cursor.head = buffer
|
||||||
result.cursor.bufferEnd = offset(buffer, len)
|
result.cursor.bufferEnd = offset(buffer, len)
|
||||||
|
|
@ -369,9 +360,9 @@ proc append*(c: var WriteCursor, chars: openarray[char]) {.inline.} =
|
||||||
var charsStart = unsafeAddr chars[0]
|
var charsStart = unsafeAddr chars[0]
|
||||||
c.append makeOpenArray(cast[ptr byte](charsStart), chars.len)
|
c.append makeOpenArray(cast[ptr byte](charsStart), chars.len)
|
||||||
|
|
||||||
template appendMemCopy*(c: var WriteCursor, value: auto) =
|
template appendMemCopy*[T](c: var WriteCursor, value: T) =
|
||||||
bind append
|
bind append
|
||||||
# TODO: add a check that this is a trivial type
|
static: assert supportsCopyMem(T)
|
||||||
let valueAddr = unsafeAddr value
|
let valueAddr = unsafeAddr value
|
||||||
c.append makeOpenArray(cast[ptr byte](valueAddr), sizeof(value))
|
c.append makeOpenArray(cast[ptr byte](valueAddr), sizeof(value))
|
||||||
|
|
||||||
|
|
@ -396,17 +387,15 @@ proc getOutput*(s: OutputStreamVar, T: type string): string =
|
||||||
result.swap s.pages[0].buffer
|
result.swap s.pages[0].buffer
|
||||||
else:
|
else:
|
||||||
result = newStringOfCap(s.pos)
|
result = newStringOfCap(s.pos)
|
||||||
for page in s.pages:
|
for page in items(s.pages):
|
||||||
result.add page.buffer.toOpenArray(page.startOffset.int,
|
result.add page.buffer.toOpenArray(page.startOffset.int,
|
||||||
page.buffer.len - 1)
|
page.buffer.len - 1)
|
||||||
|
|
||||||
template getOutput*(s: OutputStreamVar, T: type seq[byte]): seq[byte] =
|
template getOutput*(s: OutputStreamVar, T: type seq[byte]): seq[byte] =
|
||||||
cast[seq[byte]](s.getOutput(string))
|
cast[seq[byte]](s.getOutput(string))
|
||||||
|
|
||||||
proc getOutput*(s: OutputStreamVar): seq[byte] =
|
template getOutput*(s: OutputStreamVar): seq[byte] =
|
||||||
# TODO: is the extra copy here optimized away?
|
cast[seq[byte]](s.getOutput(string))
|
||||||
# Turning this proc into a template creates problems at the moment.
|
|
||||||
s.getOutput(seq[byte])
|
|
||||||
|
|
||||||
proc finishPageEarly(s: OutputStreamVar, unwrittenBytes: int) {.inline.} =
|
proc finishPageEarly(s: OutputStreamVar, unwrittenBytes: int) {.inline.} =
|
||||||
s.pages[s.pages.len - 1].buffer.setLen(s.pageSize - unwrittenBytes)
|
s.pages[s.pages.len - 1].buffer.setLen(s.pageSize - unwrittenBytes)
|
||||||
|
|
|
||||||
|
|
@ -154,11 +154,11 @@ suite "output stream":
|
||||||
|
|
||||||
test "nim odd behavior":
|
test "nim odd behavior":
|
||||||
# discovered in status-im/nim-snappy#2
|
# discovered in status-im/nim-snappy#2
|
||||||
proc encode(s: OutputStreamVar) =
|
proc encode(s: OutputStream) =
|
||||||
check true
|
check true
|
||||||
|
|
||||||
proc abc(s: OutputStreamVar) =
|
proc abc(s: OutputStream) =
|
||||||
OutputStreamVar(s.outputDevice).encode
|
OutputStream(s.outputDevice).encode
|
||||||
check true
|
check true
|
||||||
|
|
||||||
var os = new OutputStream
|
var os = new OutputStream
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue