simplex_bot_actor/src/private/jsonhooks.nim

59 lines
2.0 KiB
Nim

# SPDX-FileCopyrightText: ☭ Emery Hemingway
# SPDX-License-Identifier: Unlicense
import std/[base64, json, parseutils, tables]
import preserves
proc toPreserveHook*(js: JsonNode; E: typedesc): Preserve[E] {.gcsafe.} =
case js.kind
of JString:
var off = js.str.skip("data:")
if off == 0:
result = Preserve[E](kind: pkString, string: js.str)
else:
var mime: string
off.inc js.str.parseUntil(mime, ';', off)
var dataOff = off + js.str.skip(";base64,", off)
if dataOff != off:
var data = cast[seq[byte]](substr(js.str, dataOff).decode)
result = initRecord("mime", mime.toSymbol(E), data.toPreserve(E))
else:
result = Preserve[E](kind: pkString, string: js.str)
of JInt:
result = Preserve[E](kind: pkSignedInteger, int: 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 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)
of JObject:
if js.hasKey("type"):
var label = js.getOrDefault("type").getStr.toSymbol(E)
if js.len == 1:
result = initRecord(label)
elif js.len == 2:
for key, val in js.fields.pairs:
if key != "type":
result = initRecord(label, val.toPreserve(E))
else:
var dict = Preserve[E](kind: pkDictionary)
for key, val in js.fields.pairs:
if key != "type":
dict[Preserve[E](kind: pkString, string: key)] = toPreserveHook(val, E)
result = initRecord(label, dict)
elif js.len == 1:
for key, val in js.fields.pairs:
result = initRecord(key, val.toPreserve(E))
else:
result = Preserve[E](kind: pkDictionary)
for key, val in js.fields.pairs:
result[Preserve[E](kind: pkString, string: key)] = toPreserveHook(val, E)