Add sort and cannonicalize

This commit is contained in:
Emery Hemingway 2023-06-11 11:01:15 +01:00
parent 117aa19ef3
commit a7a90097a8
2 changed files with 26 additions and 1 deletions

View File

@ -1,6 +1,6 @@
# Package
version = "20230607"
version = "20230611"
author = "Emery Hemingway"
description = "data model and serialization format"
license = "Unlicense"

View File

@ -4,6 +4,7 @@
import std/[base64, endians, hashes, options, sets, sequtils, streams, tables, typetraits]
import ./preserves/private/macros
from std/algorithm import sort
from std/json import escapeJson, escapeJsonUnquoted
from std/strutils import parseEnum
import ./preserves/private/dot
@ -167,6 +168,30 @@ proc `<`*[A, B](x: Preserve[A]; y: Preserve[B]): bool =
when (not A is void) and (A is B):
result = x.embed < y.embed
proc cmp*[E](x, y: var Preserve[E]): int =
if x == y: 0
elif x < y: -1
else: 1
proc sort*[E](pr: var Preserve[E]) = sort(pr.sequence, cmp)
## Sort a Preserves array by total ordering.
proc cannonicalize*[E](pr: var Preserve[E]) {.gcsafe.} =
## Cannonicalize a compound Preserves value by total ordering.
case pr.kind
of pkSequence:
apply(pr.sequence, cannonicalize)
of pkSet:
apply(pr.set, cannonicalize)
sort(pr.set)
of pkDictionary:
apply(pr.dict) do (e: var DictEntry[E]):
cannonicalize(e.val)
sort(pr.dict) do (x, y: DictEntry[E]) -> int:
cmp(x.key, y.key)
else:
discard
proc hash*(pr: Preserve): Hash =
## Produce a `Hash` of `pr` for use with a `HashSet` or `Table`.
var h = hash(pr.kind.int) !& hash(pr.embedded)