Implemented serialization of OrderedMap

This commit is contained in:
Felix Krause 2016-03-25 22:22:42 +01:00
parent 06faf4966d
commit 5ec086081c
2 changed files with 102 additions and 12 deletions

View File

@ -235,16 +235,14 @@ proc representObject*[T](value: seq[T], ts: TagStyle,
## represents a Nim seq as YAML sequence ## represents a Nim seq as YAML sequence
result = iterator(): YamlStreamEvent = result = iterator(): YamlStreamEvent =
let childTagStyle = if ts == tsRootOnly: tsNone else: ts let childTagStyle = if ts == tsRootOnly: tsNone else: ts
yield YamlStreamEvent(kind: yamlStartSeq, yield startSeqEvent(tag)
seqTag: tag,
seqAnchor: yAnchorNone)
for item in value: for item in value:
var events = representChild(item, childTagStyle, c) var events = representChild(item, childTagStyle, c)
while true: while true:
let event = events() let event = events()
if finished(events): break if finished(events): break
yield event yield event
yield YamlStreamEvent(kind: yamlEndSeq) yield endSeqEvent()
proc yamlTag*[K, V](T: typedesc[Table[K, V]]): TagId {.inline, raises: [].} = proc yamlTag*[K, V](T: typedesc[Table[K, V]]): TagId {.inline, raises: [].} =
try: try:
@ -252,7 +250,7 @@ proc yamlTag*[K, V](T: typedesc[Table[K, V]]): TagId {.inline, raises: [].} =
safeTagUri(yamlTag(V)) & ")" safeTagUri(yamlTag(V)) & ")"
result = lazyLoadTag(uri) result = lazyLoadTag(uri)
except KeyError: except KeyError:
# cannot happen (theoretically, you known) # cannot happen (theoretically, you know)
assert(false) assert(false)
proc constructObject*[K, V](s: var YamlStream, c: ConstructionContext, proc constructObject*[K, V](s: var YamlStream, c: ConstructionContext,
@ -270,6 +268,8 @@ proc constructObject*[K, V](s: var YamlStream, c: ConstructionContext,
value: V value: V
constructChild(s, c, key) constructChild(s, c, key)
constructChild(s, c, value) constructChild(s, c, value)
if result.contains(key):
raise newException(YamlConstructionError, "Duplicate table key!")
result[key] = value result[key] = value
discard s.next() discard s.next()
@ -278,9 +278,7 @@ proc representObject*[K, V](value: Table[K, V], ts: TagStyle,
## represents a Nim Table as YAML mapping ## represents a Nim Table as YAML mapping
result = iterator(): YamlStreamEvent = result = iterator(): YamlStreamEvent =
let childTagStyle = if ts == tsRootOnly: tsNone else: ts let childTagStyle = if ts == tsRootOnly: tsNone else: ts
yield YamlStreamEvent(kind: yamlStartMap, yield startMapEvent(tag)
mapTag: tag,
mapAnchor: yAnchorNone)
for key, value in value.pairs: for key, value in value.pairs:
var events = representChild(key, childTagStyle, c) var events = representChild(key, childTagStyle, c)
while true: while true:
@ -292,7 +290,63 @@ proc representObject*[K, V](value: Table[K, V], ts: TagStyle,
let event = events() let event = events()
if finished(events): break if finished(events): break
yield event yield event
yield YamlStreamEvent(kind: yamlEndMap) yield endMapEvent()
proc yamlTag*[K, V](T: typedesc[OrderedTable[K, V]]): TagId
{.inline, raises: [].} =
try:
let uri = "!nim:tables:OrderedTable(" & safeTagUri(yamlTag(K)) & "," &
safeTagUri(yamlTag(V)) & ")"
result = lazyLoadTag(uri)
except KeyError:
# cannot happen (theoretically, you know)
assert(false)
proc constructObject*[K, V](s: var YamlStream, c: ConstructionContext,
result: var OrderedTable[K, V])
{.raises: [YamlConstructionError, YamlStreamError].} =
## constructs a Nim OrderedTable from a YAML mapping
let event = s.next()
if event.kind != yamlStartSeq:
raise newException(YamlConstructionError, "Expected seq start, got " &
$event.kind)
result = initOrderedTable[K, V]()
while s.peek.kind != yamlEndSeq:
var
key: K
value: V
if s.next().kind != yamlStartMap:
raise newException(YamlConstructionError,
"Expected map start, got " & $event.kind)
constructChild(s, c, key)
constructChild(s, c, value)
if s.next().kind != yamlEndMap:
raise newException(YamlConstructionError,
"Expected map end, got " & $event.kind)
if result.contains(key):
raise newException(YamlConstructionError, "Duplicate table key!")
result.add(key, value)
discard s.next()
proc representObject*[K, V](value: OrderedTable[K, V], ts: TagStyle,
c: SerializationContext, tag: TagId): RawYamlStream {.raises: [].} =
result = iterator(): YamlStreamEvent =
let childTagStyle = if ts == tsRootOnly: tsNone else: ts
yield startSeqEvent(tag)
for key, value in value.pairs:
yield startMapEvent()
var events = representChild(key, childTagStyle, c)
while true:
let event = events()
if finished(events): break
yield event
events = representChild(value, childTagStyle, c)
while true:
let event = events()
if finished(events): break
yield event
yield endMapEvent()
yield endSeqEvent()
template yamlTag*(T: typedesc[object|enum]): expr = template yamlTag*(T: typedesc[object|enum]): expr =
var uri = when compiles(yamlTagId(T)): yamlTagId(T) else: var uri = when compiles(yamlTagId(T)): yamlTagId(T) else:
@ -546,13 +600,13 @@ proc represent*[T](value: T, ts: TagStyle = tsRootOnly,
var var
context = newSerializationContext(a) context = newSerializationContext(a)
objStream = iterator(): YamlStreamEvent = objStream = iterator(): YamlStreamEvent =
yield YamlStreamEvent(kind: yamlStartDoc) yield startDocEvent()
var events = representChild(value, ts, context) var events = representChild(value, ts, context)
while true: while true:
let e = events() let e = events()
if finished(events): break if finished(events): break
yield e yield e
yield YamlStreamEvent(kind: yamlEndDoc) yield endDocEvent()
if a == asTidy: if a == asTidy:
var objQueue = newSeq[YamlStreamEvent]() var objQueue = newSeq[YamlStreamEvent]()
try: try:

View File

@ -51,7 +51,8 @@ proc constructObject*(s: var YamlStream, c: ConstructionContext,
template assertStringEqual(expected, actual: string) = template assertStringEqual(expected, actual: string) =
for i in countup(0, min(expected.len, actual.len)): for i in countup(0, min(expected.len, actual.len)):
if expected[i] != actual[i]: if expected[i] != actual[i]:
echo "string mismatch at character #", i, ":" echo "string mismatch at character #", i, "(expected:\'",
expected[i], "\', was \'", actual[i], "\'):"
echo "expected:\n", expected, "\nactual:\n", actual echo "expected:\n", expected, "\nactual:\n", actual
assert(false) assert(false)
@ -98,6 +99,41 @@ suite "Serialization":
"%YAML 1.2\n--- \n23: dreiundzwanzig\n42: zweiundvierzig", "%YAML 1.2\n--- \n23: dreiundzwanzig\n42: zweiundvierzig",
output.data) output.data)
test "Serialization: Load OrderedTable[tuple[int32, int32], string]":
let input = newStringStream("- {a: 23, b: 42}: drzw\n- {a: 13, b: 47}: drsi")
var result: OrderedTable[tuple[a, b: int32], string]
load(input, result)
var i = 0
for key, value in result.pairs:
case i
of 0:
assert key == (a: 23'i32, b: 42'i32)
assert value == "drzw"
of 1:
assert key == (a: 13'i32, b: 47'i32)
assert value == "drsi"
else: assert false
i.inc()
test "Serialization: Represent OrderedTable[tuple[int32, int32], string]":
var input = initOrderedTable[tuple[a, b: int32], string]()
input.add((a: 23'i32, b: 42'i32), "dreiundzwanzigzweiundvierzig")
input.add((a: 13'i32, b: 47'i32), "dreizehnsiebenundvierzig")
var output = newStringStream()
dump(input, output, tsRootOnly, asTidy, blockOnly)
assertStringEqual("""%YAML 1.2
--- !nim:tables:OrderedTable(nim:tuple(nim:system:int32,nim:system:int32),tag:yaml.org,2002:str)
-
?
a: 23
b: 42
: dreiundzwanzigzweiundvierzig
-
?
a: 13
b: 47
: dreizehnsiebenundvierzig""", output.data)
test "Serialization: Load Sequences in Sequence": test "Serialization: Load Sequences in Sequence":
let input = newStringStream(" - [1, 2, 3]\n - [4, 5]\n - [6]") let input = newStringStream(" - [1, 2, 3]\n - [4, 5]\n - [6]")
var result: seq[seq[int32]] var result: seq[seq[int32]]