diff --git a/private/serialization.nim b/private/serialization.nim index a73174e..2382096 100644 --- a/private/serialization.nim +++ b/private/serialization.nim @@ -387,16 +387,22 @@ proc representObject*[K, V](value: OrderedTable[K, V], ts: TagStyle, yield endMapEvent() yield endSeqEvent() +proc isVariant(t: typedesc): bool {.compileTime.} = + let typeDesc = getType(t) + if typeDesc.len > 1: + for child in typeDesc[1].children: + if child.kind == nnkRecCase: + return true + return false + proc yamlTag*(T: typedesc[object|enum]): - TagId {.inline, noSideEffect, raises: [].} = - when compiles(yamlTag(T)): result = yamlTag(T) - else: - var uri = "!nim:custom:" & (typetraits.name(type(T))) - try: serializationTagLibrary.tags[uri] - except KeyError: serializationTagLibrary.registerUri(uri) + TagId {.inline, raises: [].} = + var uri = "!nim:custom:" & (typetraits.name(type(T))) + try: serializationTagLibrary.tags[uri] + except KeyError: serializationTagLibrary.registerUri(uri) proc yamlTag*(T: typedesc[tuple]): - TagId {.inline, noSideEffect, raises: [].} = + TagId {.inline, raises: [].} = var i: T uri = "!nim:tuple(" @@ -423,10 +429,13 @@ proc constructObject*[O: object|tuple]( raise newException(YamlConstructionError, "Expected field name, got " & $e.kind) let name = e.scalarContent - for fname, value in fieldPairs(result): - if fname == name: - constructChild(s, c, value) - break + when compiles(implicitVariantObject(O)): + discard + else: + for fname, value in fieldPairs(result): + if fname == name: + constructChild(s, c, value) + break discard s.next() proc representObject*[O: object|tuple](value: O, ts: TagStyle, @@ -625,6 +634,11 @@ proc representChild*[O](value: ref O, ts: TagStyle, c: SerializationContext): yield event except KeyError: assert false, "Can never happen" +proc representChild*[O](value: O, ts: TagStyle, + c: SerializationContext): RawYamlStream = + result = representObject(value, ts, c, if ts == tsNone: + yTagQuestionMark else: yamlTag(O)) + proc construct*[T](s: var YamlStream, target: var T) = var context = newConstructionContext() try: diff --git a/test1.nim b/test1.nim deleted file mode 100644 index cb7e656..0000000 --- a/test1.nim +++ /dev/null @@ -1,27 +0,0 @@ -import yaml, macros - -type - FooKind = enum - fooInt, fooBool, fooNone - FooKind2 = enum - fooAddString, fooAddNone - - Foo = object - a: string - case b: FooKind - of fooInt: - c: int32 - of fooBool: - d: bool - of fooNone: - discard - case c2: FooKind2 - of fooAddString: - e: string - of fooAddNone: - discard - -var o = newFileStream(stdout) -var f = Foo(a: "a", b: fooBool, d: true) - -dump(f, o) \ No newline at end of file diff --git a/yaml.nim b/yaml.nim index 89280fc..1830997 100644 --- a/yaml.nim +++ b/yaml.nim @@ -624,57 +624,10 @@ proc representChild*(value: string, ts: TagStyle, c: SerializationContext): RawYamlStream {.inline.} ## Represents a Nim string. Supports nil strings. -proc isVariant(t: typedesc): bool {.compileTime.} = - let typeDesc = getType(t) - if typeDesc.len > 1: - for child in typeDesc[1].children: - if child.kind == nnkRecCase: - return true - return false - -macro presentTagDiscriminators(target: string, t: typedesc, val: expr): stmt = - var first = true - let typeDesc = getType(getType(t)[1]) - for child in typeDesc[1].children: - if child.kind != nnkRecCase: continue - - template discriminantToString(): NimNode = - newNimNode(nnkInfix).add( - newIdentNode("$"), newDotExpr(val, child[0]) - ) - - if first: - first = false - result = newNimNode(nnkInfix).add( - newIdentNode("&"), newStrLitNode("("), discriminantToString() - ) - else: - result = newNimNode(nnkInfix).add( - newIdentNode("&"), result, newNimNode(nnkInfix).add( - newIdentNode("&"), newStrLitNode(","), discriminantToString()) - ) - if first: # no discriminators - result = newNimNode(nnkDiscardStmt).add(newNimNode(nnkEmpty)) - else: - result = newNimNode(nnkInfix).add(newIdentNode("&="), target, - newNimNode(nnkInfix).add(newIdentNode("&"), result, newStrLitNode(")"))) - -template presentVariantObjectTag[O](t: typedesc[object], val: O): TagId = - var oTag = name(t) - presentTagDiscriminators(oTag, t, val) - try: serializationTagLibrary.tags[oTag] - except KeyError: serializationTagLibrary.registerUri(oTag) - proc representChild*[O](value: O, ts: TagStyle, c: SerializationContext): - RawYamlStream {.raises: [].} = + RawYamlStream {.raises: [].} ## Represents an arbitrary Nim object as YAML object. - const isVar = isVariant(O) - when isVar: - result = representObject(value, ts, c, presentVariantObjectTag(O, value)) - else: - result = representObject(value, ts, c, if ts == tsNone: - yTagQuestionMark else: yamlTag(O)) proc construct*[T](s: var YamlStream, target: var T) {.raises: [YamlConstructionError, YamlStreamError].}