2018-11-11 11:40:19 +00:00
|
|
|
import
|
2021-08-16 06:52:41 +00:00
|
|
|
std/typetraits,
|
|
|
|
stew/shims/macros, faststreams/[inputs, outputs],
|
|
|
|
./serialization/[object_serialization, errors, formats]
|
2018-11-11 11:40:19 +00:00
|
|
|
|
|
|
|
export
|
2021-08-16 06:52:41 +00:00
|
|
|
inputs, outputs, object_serialization, errors, formats
|
2021-03-18 10:55:50 +00:00
|
|
|
|
2018-12-17 23:00:00 +00:00
|
|
|
template encode*(Format: type, value: auto, params: varargs[untyped]): auto =
|
2021-03-19 02:04:14 +00:00
|
|
|
mixin init, Writer, writeValue, PreferredOutputType
|
2020-04-10 13:44:38 +00:00
|
|
|
{.noSideEffect.}:
|
|
|
|
# We assume that there is no side-effects here, because we are
|
|
|
|
# using a `memoryOutput`. The computed side-effects are coming
|
|
|
|
# from the fact that the dynamic dispatch mechanisms used in
|
|
|
|
# faststreams may be writing to a file or a network device.
|
2020-04-22 22:45:59 +00:00
|
|
|
try:
|
|
|
|
var s = memoryOutput()
|
2021-03-19 02:04:14 +00:00
|
|
|
type WriterType = Writer(Format)
|
|
|
|
var writer = unpackArgs(init, [WriterType, s, params])
|
2020-04-22 22:45:59 +00:00
|
|
|
writeValue writer, value
|
2021-03-19 02:04:14 +00:00
|
|
|
s.getOutput PreferredOutputType(Format)
|
2020-04-22 22:45:59 +00:00
|
|
|
except IOError:
|
|
|
|
raise (ref Defect)() # a memoryOutput cannot have an IOError
|
2018-12-17 23:00:00 +00:00
|
|
|
|
2020-04-22 22:45:59 +00:00
|
|
|
# TODO Nim cannot make sense of this initialization by var param?
|
|
|
|
{.push warning[ProveInit]: off.}
|
2018-12-17 23:00:00 +00:00
|
|
|
proc readValue*(reader: var auto, T: type): T =
|
|
|
|
mixin readValue
|
|
|
|
reader.readValue(result)
|
2020-04-22 22:45:59 +00:00
|
|
|
{.pop.}
|
2018-12-17 23:00:00 +00:00
|
|
|
|
|
|
|
template decode*(Format: distinct type,
|
2020-04-14 16:34:44 +00:00
|
|
|
input: string,
|
2019-01-21 17:39:18 +00:00
|
|
|
RecordType: distinct type,
|
|
|
|
params: varargs[untyped]): auto =
|
2019-03-11 09:34:04 +00:00
|
|
|
# TODO, this is dusplicated only due to a Nim bug:
|
2021-12-05 14:52:47 +00:00
|
|
|
# If `input` was `string|openArray[byte]`, it won't match `seq[byte]`
|
2021-03-19 02:04:14 +00:00
|
|
|
mixin init, Reader
|
2020-04-10 13:44:38 +00:00
|
|
|
{.noSideEffect.}:
|
|
|
|
# We assume that there are no side-effects here, because we are
|
|
|
|
# using a `memoryInput`. The computed side-effects are coming
|
|
|
|
# from the fact that the dynamic dispatch mechanisms used in
|
|
|
|
# faststreams may be reading from a file or a network device.
|
2020-04-22 22:45:59 +00:00
|
|
|
try:
|
2020-05-05 17:29:26 +00:00
|
|
|
var stream = unsafeMemoryInput(input)
|
2021-03-19 02:04:14 +00:00
|
|
|
type ReaderType = Reader(Format)
|
|
|
|
var reader = unpackArgs(init, [ReaderType, stream, params])
|
2020-04-22 22:45:59 +00:00
|
|
|
reader.readValue(RecordType)
|
|
|
|
except IOError:
|
2020-05-05 17:29:26 +00:00
|
|
|
raise (ref Defect)() # memory inputs cannot raise an IOError
|
2019-03-11 09:34:04 +00:00
|
|
|
|
|
|
|
template decode*(Format: distinct type,
|
2021-12-05 14:52:47 +00:00
|
|
|
input: openArray[byte],
|
2019-03-11 09:34:04 +00:00
|
|
|
RecordType: distinct type,
|
|
|
|
params: varargs[untyped]): auto =
|
|
|
|
# TODO, this is dusplicated only due to a Nim bug:
|
2021-12-05 14:52:47 +00:00
|
|
|
# If `input` was `string|openArray[byte]`, it won't match `seq[byte]`
|
2021-03-19 02:04:14 +00:00
|
|
|
mixin init, Reader
|
2020-04-10 13:44:38 +00:00
|
|
|
{.noSideEffect.}:
|
|
|
|
# We assume that there are no side-effects here, because we are
|
|
|
|
# using a `memoryInput`. The computed side-effects are coming
|
|
|
|
# from the fact that the dynamic dispatch mechanisms used in
|
|
|
|
# faststreams may be reading from a file or a network device.
|
2020-04-22 22:45:59 +00:00
|
|
|
try:
|
2020-05-05 17:29:26 +00:00
|
|
|
var stream = unsafeMemoryInput(input)
|
2021-03-19 02:04:14 +00:00
|
|
|
type ReaderType = Reader(Format)
|
|
|
|
var reader = unpackArgs(init, [ReaderType, stream, params])
|
2020-04-22 22:45:59 +00:00
|
|
|
reader.readValue(RecordType)
|
|
|
|
except IOError:
|
2020-05-05 17:29:26 +00:00
|
|
|
raise (ref Defect)() # memory inputs cannot raise an IOError
|
2018-12-17 23:00:00 +00:00
|
|
|
|
|
|
|
template loadFile*(Format: distinct type,
|
|
|
|
filename: string,
|
2019-01-21 17:39:18 +00:00
|
|
|
RecordType: distinct type,
|
|
|
|
params: varargs[untyped]): auto =
|
2021-03-19 02:04:14 +00:00
|
|
|
mixin init, Reader, readValue
|
2019-09-11 18:09:58 +00:00
|
|
|
|
2020-05-06 12:07:35 +00:00
|
|
|
var stream = memFileInput(filename)
|
2020-04-22 18:26:02 +00:00
|
|
|
try:
|
2021-03-19 02:04:14 +00:00
|
|
|
type ReaderType = Reader(Format)
|
|
|
|
var reader = unpackArgs(init, [ReaderType, stream, params])
|
2020-04-22 18:26:02 +00:00
|
|
|
reader.readValue(RecordType)
|
|
|
|
finally:
|
|
|
|
close stream
|
2019-01-21 17:39:18 +00:00
|
|
|
|
2018-12-17 23:00:00 +00:00
|
|
|
template loadFile*[RecordType](Format: type,
|
|
|
|
filename: string,
|
2019-01-21 17:39:18 +00:00
|
|
|
record: var RecordType,
|
|
|
|
params: varargs[untyped]) =
|
|
|
|
record = loadFile(Format, filename, RecordType, params)
|
2018-11-10 00:14:43 +00:00
|
|
|
|
2020-04-14 16:34:44 +00:00
|
|
|
template saveFile*(Format: type, filename: string, value: auto, params: varargs[untyped]) =
|
2021-03-19 02:04:14 +00:00
|
|
|
mixin init, Writer, writeValue
|
2020-04-14 16:34:44 +00:00
|
|
|
|
|
|
|
var stream = fileOutput(filename)
|
2020-04-22 18:26:02 +00:00
|
|
|
try:
|
2021-03-19 02:04:14 +00:00
|
|
|
type WriterType = Writer(Format)
|
|
|
|
var writer = unpackArgs(init, [WriterType, stream, params])
|
2020-04-22 18:26:02 +00:00
|
|
|
writer.writeValue(value)
|
|
|
|
finally:
|
|
|
|
close stream
|
2018-11-29 01:33:45 +00:00
|
|
|
|
2020-06-23 19:21:49 +00:00
|
|
|
template borrowSerialization*(Alias: type) {.dirty.} =
|
|
|
|
bind distinctBase
|
|
|
|
|
|
|
|
proc writeValue*[Writer](writer: var Writer, value: Alias) =
|
|
|
|
mixin writeValue
|
|
|
|
writeValue(writer, distinctBase value)
|
|
|
|
|
|
|
|
proc readValue*[Reader](reader: var Reader, value: var Alias) =
|
|
|
|
mixin readValue
|
|
|
|
value = Alias reader.readValue(distinctBase Alias)
|
|
|
|
|
2019-03-13 21:20:27 +00:00
|
|
|
template borrowSerialization*(Alias: distinct type,
|
|
|
|
OriginalType: distinct type) {.dirty.} =
|
|
|
|
|
|
|
|
proc writeValue*[Writer](writer: var Writer, value: Alias) =
|
|
|
|
mixin writeValue
|
|
|
|
writeValue(writer, OriginalType value)
|
|
|
|
|
|
|
|
proc readValue*[Reader](reader: var Reader, value: var Alias) =
|
|
|
|
mixin readValue
|
|
|
|
value = Alias reader.readValue(OriginalType)
|
|
|
|
|
2020-06-23 19:21:49 +00:00
|
|
|
template serializesAsBase*(SerializedType: distinct type,
|
|
|
|
Format: distinct type) =
|
2021-03-19 02:04:14 +00:00
|
|
|
mixin Reader, Writer
|
2020-06-23 19:21:49 +00:00
|
|
|
|
2021-03-19 02:04:14 +00:00
|
|
|
type ReaderType = Reader(Format)
|
|
|
|
type WriterType = Writer(Format)
|
2020-06-23 19:21:49 +00:00
|
|
|
|
2021-03-19 02:04:14 +00:00
|
|
|
template writeValue*(writer: var WriterType, value: SerializedType) =
|
2020-06-23 19:21:49 +00:00
|
|
|
mixin writeValue
|
|
|
|
writeValue(writer, distinctBase value)
|
|
|
|
|
2021-03-19 02:04:14 +00:00
|
|
|
template readValue*(reader: var ReaderType, value: var SerializedType) =
|
2020-06-23 19:21:49 +00:00
|
|
|
mixin readValue
|
|
|
|
value = SerializedType reader.readValue(distinctBase SerializedType)
|
|
|
|
|
|
|
|
macro serializesAsBaseIn*(SerializedType: type,
|
|
|
|
Formats: varargs[untyped]) =
|
|
|
|
result = newStmtList()
|
|
|
|
for Fmt in Formats:
|
|
|
|
result.add newCall(bindSym"serializesAsBase", SerializedType, Fmt)
|
|
|
|
|
2020-05-06 19:46:54 +00:00
|
|
|
template readValue*(stream: InputStream,
|
|
|
|
Format: type,
|
|
|
|
ValueType: type,
|
|
|
|
params: varargs[untyped]): untyped =
|
2021-03-19 02:04:14 +00:00
|
|
|
mixin Reader, init, readValue
|
|
|
|
type ReaderType = Reader(Format)
|
|
|
|
var reader = unpackArgs(init, [ReaderType, stream, params])
|
2020-05-06 19:46:54 +00:00
|
|
|
readValue reader, ValueType
|
|
|
|
|
|
|
|
template writeValue*(stream: OutputStream,
|
|
|
|
Format: type,
|
|
|
|
value: auto,
|
|
|
|
params: varargs[untyped]) =
|
2021-03-19 02:04:14 +00:00
|
|
|
mixin Writer, init, writeValue
|
|
|
|
type WriterType = Writer(Format)
|
|
|
|
var writer = unpackArgs(init, [WriterType, stream, params])
|
2019-06-24 02:07:13 +00:00
|
|
|
writeValue writer, value
|
|
|
|
|