Option support in toPreserves and fromPreserves
This commit is contained in:
parent
501d6cc012
commit
0acd369262
|
@ -1,6 +1,6 @@
|
||||||
# Package
|
# Package
|
||||||
|
|
||||||
version = "20240102"
|
version = "20240103"
|
||||||
author = "Emery Hemingway"
|
author = "Emery Hemingway"
|
||||||
description = "data model and serialization format"
|
description = "data model and serialization format"
|
||||||
license = "Unlicense"
|
license = "Unlicense"
|
||||||
|
|
|
@ -142,15 +142,6 @@ proc `&`*(x: Value; y: seq[Value]): Value =
|
||||||
raise newException(ValueError, "cannot concatenate to non-sequence value")
|
raise newException(ValueError, "cannot concatenate to non-sequence value")
|
||||||
result = Value(kind: pkSequence, sequence: x.sequence & y)
|
result = Value(kind: pkSequence, sequence: x.sequence & y)
|
||||||
|
|
||||||
proc getOrDefault(pr, key: Value): Value =
|
|
||||||
## Retrieves the value of `pr[key]` if `pr` is a dictionary containing `key`
|
|
||||||
## or returns the `#f` Preserves value.
|
|
||||||
if pr.kind == pkDictionary:
|
|
||||||
for (k, v) in pr.dict:
|
|
||||||
if key == k:
|
|
||||||
result = v
|
|
||||||
break
|
|
||||||
|
|
||||||
proc pop*(pr: var Value; key: Value; val: var Value): bool =
|
proc pop*(pr: var Value; key: Value; val: var Value): bool =
|
||||||
## Deletes the `key` from a Preserves dictionary.
|
## Deletes the `key` from a Preserves dictionary.
|
||||||
## Returns true, if the key existed, and sets `val` to the mapping
|
## Returns true, if the key existed, and sets `val` to the mapping
|
||||||
|
@ -440,9 +431,15 @@ proc toPreserves*[T](x: T): Value {.gcsafe.} =
|
||||||
elif T.hasCustomPragma(preservesDictionary):
|
elif T.hasCustomPragma(preservesDictionary):
|
||||||
result = initDictionary()
|
result = initDictionary()
|
||||||
for key, val in x.fieldPairs:
|
for key, val in x.fieldPairs:
|
||||||
var pr = fieldToPreserve(key, val)
|
when val is Option:
|
||||||
applyEmbed(key, pr)
|
if val.isSome:
|
||||||
result[toSymbol(key)] = pr
|
var pr = fieldToPreserve(key, val.get)
|
||||||
|
applyEmbed(key, pr)
|
||||||
|
result[key.toSymbol] = pr
|
||||||
|
else:
|
||||||
|
var pr = fieldToPreserve(key, val)
|
||||||
|
applyEmbed(key, pr)
|
||||||
|
result[key.toSymbol] = pr
|
||||||
sortDict(result)
|
sortDict(result)
|
||||||
else:
|
else:
|
||||||
{.warning: "failed to preserve object " & $T .}
|
{.warning: "failed to preserve object " & $T .}
|
||||||
|
@ -491,6 +488,9 @@ proc toPreservesHook*[A, B](table: Table[A, B]|TableRef[A, B]): Value =
|
||||||
result[toPreserves(k)] = toPreserves(v)
|
result[toPreserves(k)] = toPreserves(v)
|
||||||
sortDict(result)
|
sortDict(result)
|
||||||
|
|
||||||
|
proc toPreservesHook*(o: Option): Value =
|
||||||
|
o.get.toPreserves
|
||||||
|
|
||||||
proc fromAtom*[T](v: var T; a: ATom): bool =
|
proc fromAtom*[T](v: var T; a: ATom): bool =
|
||||||
if T is Atom:
|
if T is Atom:
|
||||||
v = a
|
v = a
|
||||||
|
@ -715,12 +715,17 @@ proc fromPreserves*[T](v: var T; pr: Value): bool {.gcsafe.} =
|
||||||
if pr.isDictionary:
|
if pr.isDictionary:
|
||||||
result = true
|
result = true
|
||||||
var i: int
|
var i: int
|
||||||
for key, _ in fieldPairs(v):
|
for key, field in fieldPairs(v):
|
||||||
let val = pr.getOrDefault(toSymbol(key))
|
|
||||||
result = result and fieldFromPreserve(
|
|
||||||
key, v.dot(key), val)
|
|
||||||
if not result: break
|
if not result: break
|
||||||
inc i
|
let val = step(pr, key.toSymbol)
|
||||||
|
when field is Option:
|
||||||
|
if val.isSome:
|
||||||
|
discard fieldFromPreserve(key, v.dot(key), val.get)
|
||||||
|
else:
|
||||||
|
inc i
|
||||||
|
result = result and val.isSome
|
||||||
|
if result:
|
||||||
|
result = result and fieldFromPreserve(key, v.dot(key), val.get)
|
||||||
result = result and (i <= pr.len)
|
result = result and (i <= pr.len)
|
||||||
elif T.hasCustomPragma(preservesOr):
|
elif T.hasCustomPragma(preservesOr):
|
||||||
for kind in typeof(T.orKind):
|
for kind in typeof(T.orKind):
|
||||||
|
@ -740,9 +745,11 @@ proc fromPreserves*[T](v: var T; pr: Value): bool {.gcsafe.} =
|
||||||
result = true
|
result = true
|
||||||
var i: int
|
var i: int
|
||||||
for key, _ in fieldPairs(v):
|
for key, _ in fieldPairs(v):
|
||||||
let val = pr.getOrDefault(toSymbol(key))
|
|
||||||
result = result and fieldFromPreserve(key, v.dot(key), val)
|
|
||||||
if not result: break
|
if not result: break
|
||||||
|
let val = step(pr, key.toSymbol)
|
||||||
|
result = result and val.isSome
|
||||||
|
if result:
|
||||||
|
result = result and fieldFromPreserve(key, v.dot(key), val.get)
|
||||||
inc i
|
inc i
|
||||||
result = result and (i <= pr.len)
|
result = result and (i <= pr.len)
|
||||||
else:
|
else:
|
||||||
|
@ -811,6 +818,12 @@ proc fromPreservesHook*[A,B](t: var (Table[A,B]|TableRef[A,B]); pr: Value): bool
|
||||||
break
|
break
|
||||||
t[move a] = move b
|
t[move a] = move b
|
||||||
|
|
||||||
|
proc fromPreservesHook*[T](opt: var Option[T]; pr: Value): bool =
|
||||||
|
opt = some(default T)
|
||||||
|
result = opt.get.fromPreserves(pr)
|
||||||
|
if not result:
|
||||||
|
opt = none(T)
|
||||||
|
|
||||||
when isMainModule:
|
when isMainModule:
|
||||||
var t: Table[int, string]
|
var t: Table[int, string]
|
||||||
var pr = t.toPreservesHook()
|
var pr = t.toPreservesHook()
|
||||||
|
|
|
@ -17,11 +17,13 @@ suite "conversions":
|
||||||
a: int
|
a: int
|
||||||
b: seq[int]
|
b: seq[int]
|
||||||
c {.preservesEmbedded.}: Bar
|
c {.preservesEmbedded.}: Bar
|
||||||
|
d: Option[bool]
|
||||||
|
e: Option[bool]
|
||||||
let
|
let
|
||||||
c = Foobar(a: 1, b: @[2], c: ("ku", ))
|
c = Foobar(a: 1, b: @[2], c: ("ku", ), e: some(true))
|
||||||
b = toPreserves(c)
|
b = toPreserves(c)
|
||||||
a = preservesTo(b, Foobar)
|
a = preservesTo(b, Foobar)
|
||||||
check($b == """{a: 1 b: [2] c: #!["ku"]}""")
|
check($b == """{a: 1 b: [2] c: #!["ku"] e: #t}""")
|
||||||
check(a.isSome)
|
check(a.isSome)
|
||||||
if a.isSome: check(get(a) == c)
|
if a.isSome: check(get(a) == c)
|
||||||
check(b.kind == pkDictionary)
|
check(b.kind == pkDictionary)
|
||||||
|
|
Loading…
Reference in New Issue