From c8c8e3b7e27cd0d14d00a72bc8f6af0aaad58cf0 Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Sun, 11 Nov 2018 13:40:19 +0200 Subject: [PATCH] Initial simple/naive implementation of the field enumeration logic --- serialization.nim | 7 +++- serialization.nimble | 13 +------ serialization/object_serialization.nim | 52 ++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 14 deletions(-) create mode 100644 serialization/object_serialization.nim diff --git a/serialization.nim b/serialization.nim index 23bef05..fdcd59f 100644 --- a/serialization.nim +++ b/serialization.nim @@ -1,5 +1,8 @@ -import streams -export streams +import + serialization/[streams, object_serialization] + +export + streams, object_serialization proc encode*(Writer: type, value: auto): auto = # TODO: define a concept for the Writer types diff --git a/serialization.nimble b/serialization.nimble index 82c032b..58be127 100644 --- a/serialization.nimble +++ b/serialization.nimble @@ -3,19 +3,8 @@ mode = ScriptMode.Verbose packageName = "serialization" version = "0.1.0" author = "Status Research & Development GmbH" -description = "A modern extensible serialization framework for Nim" +description = "A modern and extensible serialization framework for Nim" license = "Apache License 2.0" skipDirs = @["tests"] requires "nim >= 0.19.0" - -proc configForTests() = - --hints: off - --debuginfo - --path: "." - --run - -task test, "run tests": - configForTests() - setCommand "c", "tests/all.nim" - diff --git a/serialization/object_serialization.nim b/serialization/object_serialization.nim new file mode 100644 index 0000000..156cb54 --- /dev/null +++ b/serialization/object_serialization.nim @@ -0,0 +1,52 @@ +import macros + +template dontSerialize* {.pragma.} + ## Specifies that a certain field should be ignored for + ## the purposes of serialization + +template customSerialization* {.pragma.} + ## This pragma can be applied to a record field to enable the + ## use of custom `readValue` overloads that also take a reference + ## to the object holding the field. + ## + ## TODO: deprecate this in favor of readField(T, field, InputArchive) + +template eachSerializedFieldImpl*[T](x: T, op: untyped) = + for k, v in fieldPairs(x): + when not hasCustomPragma(v, dontSerialize): + op(k, v) + +proc totalSerializedFieldsImpl(T: type): int = + mixin eachSerializedFieldImpl + + proc helper: int = + var dummy: T + template countFields(x) = inc result + eachSerializedFieldImpl(dummy, countFields) + + const res = helper() + return res + +template totalSerializedFields*(T: type): int = + (static(totalSerializedFieldsImpl(T))) + +macro serialziedFields*(T: typedesc, fields: varargs[untyped]): untyped = + var body = newStmtList() + let + ins = genSym(nskParam, "instance") + op = genSym(nskParam, "op") + + for field in fields: + body.add quote do: `op`(`ins`.`field`) + + result = quote do: + template eachSerializedFieldImpl*(`ins`: `T`, `op`: untyped) {.inject.} = + `body` + +template serializeFields*(value: auto, fieldName, fieldValue, body: untyped) = + # TODO: this would be nicer as a for loop macro + mixin eachSerializedFieldImpl + + template op(fieldName, fieldValue: untyped) = body + eachSerializedFieldImpl(value, op) +