# SPDX-FileCopyrightText: ☭ Emery Hemingway # SPDX-License-Identifier: Unlicense import std/[json, tables] import ../preserves proc toPreserveHook*(js: JsonNode; E: typedesc): Preserve[E] = case js.kind of JString: result = Preserve[E](kind: pkString, string: js.str) of JInt: result = Preserve[E](kind: pkRegister, register: js.num) of JFloat: result = Preserve[E](kind: pkDouble, double: js.fnum) of JBool: result = case js.bval of false: toSymbol("false", E) of true: toSymbol("true", E) of JNull: result = toSymbol("null", E) of JObject: result = Preserve[E](kind: pkDictionary) for key, val in js.fields.pairs: result[Preserve[E](kind: pkSymbol, symbol: Symbol key)] = toPreserveHook(val, E) of JArray: result = Preserve[E](kind: pkSequence, sequence: newSeq[Preserve[E]](js.elems.len)) for i, e in js.elems: result.sequence[i] = toPreserveHook(e, E) proc fromPreserveHook*[E](js: var JsonNode; prs: Preserve[E]): bool = runnableExamples: import std/json var js = JsonNode() var pr = js.toPreserveHook(void) assert fromPreserveHook(js, pr) fromJsonHook(pr, js) js = toJsonHook(pr) case prs.kind: of pkBoolean: js = newJBool(prs.bool) of pkFloat: js = newJFloat(prs.float) of pkDouble: js = newJFloat(prs.double) of pkRegister: js = newJInt(prs.register) of pkString: js = newJString(prs.string) of pkSymbol: case prs.symbol.string of "false": js = newJBool(false) of "true": js = newJBool(true) of "null": js = newJNull() else: return false of pkSequence: js = newJArray() js.elems.setLen(prs.sequence.len) for i, val in prs.sequence: if not fromPreserveHook(js.elems[i], val): return false of pkSet: js = newJArray() js.elems.setLen(prs.set.len) var i: int for val in prs.set: if not fromPreserveHook(js.elems[i], val): return false inc i of pkDictionary: js = newJObject() for (key, val) in prs.dict.items: case key.kind of pkSymbol: var jsVal: JsonNode if not fromPreserveHook(jsVal, val): return false js[string key.symbol] = jsVal of pkString: var jsVal: JsonNode if not fromPreserveHook(jsVal, val): return false js[key.string] = jsVal else: return false else: return false true proc toJsonHook*[E](pr: Preserve[E]): JsonNode = if not fromPreserveHook(result, pr): raise newException(ValueError, "cannot convert Preserves value to JSON") proc fromJsonHook*[E](pr: var Preserve[E]; js: JsonNode) = pr = toPreserveHook(js, E)