From d987b607e59806c798c993471432a2bde7c8da8a Mon Sep 17 00:00:00 2001 From: Felix Krause Date: Wed, 21 Sep 2016 15:40:03 +0200 Subject: [PATCH] Check for custom object errors when loading * Ensure no duplicate fields * Ensure no missing fields * Ensure no unknown fields * Implemented for both tuples and objects, including variant objects --- test/tserialization.nim | 42 +++++++++++++ yaml/serialization.nim | 131 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 162 insertions(+), 11 deletions(-) diff --git a/test/tserialization.nim b/test/tserialization.nim index f54d228..6a117c2 100644 --- a/test/tserialization.nim +++ b/test/tserialization.nim @@ -302,6 +302,24 @@ suite "Serialization": var output = dump(input, tsNone) assertStringEqual "%YAML 1.2\n--- \nstr: value\ni: 42\nb: y", output + test "Load Tuple - unknown field": + let input = "str: value\nfoo: bar\ni: 42\nb: true" + var result: MyTuple + expect(YamlConstructionError): + load(input, result) + + test "Load Tuple - missing field": + let input = "str: value\nb: true" + var result: MyTuple + expect(YamlConstructionError): + load(input, result) + + test "Load Tuple - duplicate field": + let input = "str: value\ni: 42\nb: true\nb: true" + var result: MyTuple + expect(YamlConstructionError): + load(input, result) + test "Load Multiple Documents": let input = newStringStream("1\n---\n2") var result: seq[int] @@ -331,6 +349,24 @@ suite "Serialization": assertStringEqual( "%YAML 1.2\n--- \nfirstnamechar: P\nsurname: Pan\nage: 12", output) + test "Load custom object - unknown field": + let input = "firstnamechar: P\nsurname: Pan\nage: 12\noccupation: free" + var result: Person + expect(YamlConstructionError): + load(input, result) + + test "Load custom object - missing field": + let input = "surname: Pan\nage: 12" + var result: Person + expect(YamlConstructionError): + load(input, result) + + test "Load custom object - duplicate field": + let input = "firstnamechar: P\nsurname: Pan\nage: 12\nsurname: Pan" + var result: Person + expect(YamlConstructionError): + load(input, result) + test "Load sequence with explicit tags": let input = newStringStream("--- !nim:system:seq(" & "tag:yaml.org,2002:str)\n- !!str one\n- !!str two") @@ -396,6 +432,12 @@ suite "Serialization": - barkometer: 13""", output + test "Load custom variant object - missing field": + let input = "{name: Bastet, kind: akCat}" + var result: Animal + expect(YamlConstructionError): + load(input, result) + test "Dump cyclic data structure": var a = newNode("a") diff --git a/yaml/serialization.nim b/yaml/serialization.nim index beac9d3..53009e2 100644 --- a/yaml/serialization.nim +++ b/yaml/serialization.nim @@ -468,10 +468,84 @@ proc yamlTag*(T: typedesc[tuple]): try: serializationTagLibrary.tags[uri] except KeyError: serializationTagLibrary.registerUri(uri) -macro constructFieldValue(t: typedesc, stream: untyped, context: untyped, - name: untyped, o: untyped): typed = +proc fieldAnalyzer(t: typedesc): tuple[sections, maxlen: int] {.compileTime.} = + result = (1, 0) let tDesc = getType(getType(t)[1]) + echo "fieldAnalyzer: " & tDesc.treeRepr + if tDesc.kind == nnkBracketExpr: + # tuple + result.maxlen = tDesc.len - 1 + else: + # object + var outerLen = 0 + for child in tDesc[2].children: + inc(outerLen) + if child.kind == nnkRecCase: + inc(result.sections) + var innerLen = 0 + for bIndex in 1..