Option support in toPreserves and fromPreserves
This commit is contained in:
parent
501d6cc012
commit
0acd369262
|
@ -1,6 +1,6 @@
|
|||
# Package
|
||||
|
||||
version = "20240102"
|
||||
version = "20240103"
|
||||
author = "Emery Hemingway"
|
||||
description = "data model and serialization format"
|
||||
license = "Unlicense"
|
||||
|
|
|
@ -142,15 +142,6 @@ proc `&`*(x: Value; y: seq[Value]): Value =
|
|||
raise newException(ValueError, "cannot concatenate to non-sequence value")
|
||||
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 =
|
||||
## Deletes the `key` from a Preserves dictionary.
|
||||
## 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):
|
||||
result = initDictionary()
|
||||
for key, val in x.fieldPairs:
|
||||
var pr = fieldToPreserve(key, val)
|
||||
applyEmbed(key, pr)
|
||||
result[toSymbol(key)] = pr
|
||||
when val is Option:
|
||||
if val.isSome:
|
||||
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)
|
||||
else:
|
||||
{.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)
|
||||
sortDict(result)
|
||||
|
||||
proc toPreservesHook*(o: Option): Value =
|
||||
o.get.toPreserves
|
||||
|
||||
proc fromAtom*[T](v: var T; a: ATom): bool =
|
||||
if T is Atom:
|
||||
v = a
|
||||
|
@ -715,12 +715,17 @@ proc fromPreserves*[T](v: var T; pr: Value): bool {.gcsafe.} =
|
|||
if pr.isDictionary:
|
||||
result = true
|
||||
var i: int
|
||||
for key, _ in fieldPairs(v):
|
||||
let val = pr.getOrDefault(toSymbol(key))
|
||||
result = result and fieldFromPreserve(
|
||||
key, v.dot(key), val)
|
||||
for key, field in fieldPairs(v):
|
||||
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)
|
||||
elif T.hasCustomPragma(preservesOr):
|
||||
for kind in typeof(T.orKind):
|
||||
|
@ -740,9 +745,11 @@ proc fromPreserves*[T](v: var T; pr: Value): bool {.gcsafe.} =
|
|||
result = true
|
||||
var i: int
|
||||
for key, _ in fieldPairs(v):
|
||||
let val = pr.getOrDefault(toSymbol(key))
|
||||
result = result and fieldFromPreserve(key, v.dot(key), val)
|
||||
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
|
||||
result = result and (i <= pr.len)
|
||||
else:
|
||||
|
@ -811,6 +818,12 @@ proc fromPreservesHook*[A,B](t: var (Table[A,B]|TableRef[A,B]); pr: Value): bool
|
|||
break
|
||||
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:
|
||||
var t: Table[int, string]
|
||||
var pr = t.toPreservesHook()
|
||||
|
|
|
@ -17,11 +17,13 @@ suite "conversions":
|
|||
a: int
|
||||
b: seq[int]
|
||||
c {.preservesEmbedded.}: Bar
|
||||
d: Option[bool]
|
||||
e: Option[bool]
|
||||
let
|
||||
c = Foobar(a: 1, b: @[2], c: ("ku", ))
|
||||
c = Foobar(a: 1, b: @[2], c: ("ku", ), e: some(true))
|
||||
b = toPreserves(c)
|
||||
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)
|
||||
if a.isSome: check(get(a) == c)
|
||||
check(b.kind == pkDictionary)
|
||||
|
|
Loading…
Reference in New Issue