From a7a90097a8cf4e866001a436944ebdddeeb646d4 Mon Sep 17 00:00:00 2001 From: Emery Hemingway Date: Sun, 11 Jun 2023 11:01:15 +0100 Subject: [PATCH] Add sort and cannonicalize --- preserves.nimble | 2 +- src/preserves.nim | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/preserves.nimble b/preserves.nimble index cb5e18d..336760e 100644 --- a/preserves.nimble +++ b/preserves.nimble @@ -1,6 +1,6 @@ # Package -version = "20230607" +version = "20230611" author = "Emery Hemingway" description = "data model and serialization format" license = "Unlicense" diff --git a/src/preserves.nim b/src/preserves.nim index 50ecae4..b5d8d3d 100644 --- a/src/preserves.nim +++ b/src/preserves.nim @@ -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)