diff --git a/doc/serialization.txt b/doc/serialization.txt index ebc0676..811b244 100644 --- a/doc/serialization.txt +++ b/doc/serialization.txt @@ -66,11 +66,11 @@ To support new scalar types, you must implement the ``constructObject()`` and Collection Types ---------------- -NimYAML supports Nim's ``seq`` and ``Table`` types out of the box. Unlike the -native YAML types ``!!seq`` and ``!!map``, ``seq`` and ``Table`` define the type -of all their items (or keys and values). So YAML objects with heterogeneous -types in them cannot be loaded to Nim collection types. For example, this -sequence: +NimYAML supports Nim's ``array``, ``set``, ``seq``, ``Table`` and +``OrderedTable`` types out of the box. Unlike the native YAML types ``!!seq`` +and ``!!map``, Nim's collection types define the type of all their contained +items (or keys and values). So YAML objects with heterogeneous types in them +cannot be loaded to Nim collection types. For example, this sequence: .. code-block:: yaml diff --git a/private/serialization.nim b/private/serialization.nim index 1cdb183..0f38c85 100644 --- a/private/serialization.nim +++ b/private/serialization.nim @@ -259,6 +259,42 @@ proc representObject*[T](value: seq[T]|set[T], ts: TagStyle, yield event yield endSeqEvent() +proc yamlTag*[I, V](T: typedesc[array[I, V]]): TagId {.inline, raises: [].} = + const rangeName = name(I) + let uri = "!nim:system:array(" & rangeName[6..rangeName.high()] & "," & + safeTagUri(yamlTag(V)) & ')' + result = lazyLoadTag(uri) + +proc constructObject*[I, T](s: var YamlStream, c: ConstructionContext, + result: var array[I, T]) + {.raises: [YamlConstructionError, YamlStreamError].} = + ## constructs a Nim array from a YAML sequence + var event = s.next() + if event.kind != yamlStartSeq: + raise newException(YamlConstructionError, "Expected sequence start") + for index in low(I)..high(I): + event = s.peek() + if event.kind == yamlEndSeq: + raise newException(YamlConstructionError, "Too few array values") + constructChild(s, c, result[index]) + event = s.next() + if event.kind != yamlEndSeq: + raise newException(YamlConstructionError, "Too much array values") + +proc representObject*[I, T](value: array[I, T], ts: TagStyle, + c: SerializationContext, tag: TagId): RawYamlStream {.raises: [].} = + ## represents a Nim array as YAML sequence + result = iterator(): YamlStreamEvent = + let childTagStyle = if ts == tsRootOnly: tsNone else: ts + yield startSeqEvent(tag) + for item in value: + var events = representChild(item, childTagStyle, c) + while true: + let event = events() + if finished(events): break + yield event + yield endSeqEvent() + proc yamlTag*[K, V](T: typedesc[Table[K, V]]): TagId {.inline, raises: [].} = try: let uri = "!nim:tables:Table(" & safeTagUri(yamlTag(K)) & "," & diff --git a/test/serializing.nim b/test/serializing.nim index 1eff566..cb9434a 100644 --- a/test/serializing.nim +++ b/test/serializing.nim @@ -92,6 +92,20 @@ suite "Serialization": var output = newStringStream() dump(input, output, tsNone, asTidy, blockOnly) assertStringEqual "%YAML 1.2\n--- \n- a\n- b", output.data + + test "Serialization: Load array": + let input = newStringStream("- 23\n- 42\n- 47") + var result: array[0..2, int32] + load(input, result) + assert result[0] == 23 + assert result[1] == 42 + assert result[2] == 47 + + test "Serialization: Represent array": + let input = [23'i32, 42'i32, 47'i32] + var output = newStringStream() + dump(input, output, tsNone, asTidy, blockOnly) + assertStringEqual "%YAML 1.2\n--- \n- 23\n- 42\n- 47", output.data test "Serialization: Load Table[int, string]": let input = newStringStream("23: dreiundzwanzig\n42: zweiundvierzig")