mirror of
https://github.com/waku-org/nwaku.git
synced 2025-01-16 09:55:07 +00:00
195 lines
6.3 KiB
Nim
195 lines
6.3 KiB
Nim
# toml-serialization
|
|
# Copyright (c) 2020 Status Research & Development GmbH
|
|
# Licensed and distributed under either of
|
|
# * MIT license: [LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT
|
|
# * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
|
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
|
|
|
import
|
|
tables, typetraits, strutils,
|
|
types, private/utils
|
|
|
|
proc innerValue(n: TomlValueRef, T: type): T =
|
|
when T is (SomeInteger or SomeFloat):
|
|
case n.kind
|
|
of TomlKind.Int: result = T(n.intVal)
|
|
of TomlKind.Float: result = T(n.floatVal)
|
|
else: discard
|
|
elif T is bool:
|
|
if n.kind == TomlKind.Bool:
|
|
result = n.boolVal
|
|
elif T is string:
|
|
if n.kind == TomlKind.String:
|
|
result = n.stringVal
|
|
elif T is TomlDateTime:
|
|
if n.kind == TomlKind.DateTime:
|
|
result = n.dateTime
|
|
elif T is TomlDate:
|
|
if n.kind == TomlKind.DateTime:
|
|
if n.dateTime.date.isSome:
|
|
result = n.dateDimte.date.get
|
|
elif T is TomlTime:
|
|
if n.kind == TomlKind.DateTime:
|
|
if n.dateTime.time.isSome:
|
|
result = n.dateDimte.time.get
|
|
elif T is enum:
|
|
case n.kind:
|
|
of TomlKind.Int: result = T(n.intVal)
|
|
of TomlKind.String: result = parseEnum[T](n.stringVal)
|
|
else: discard
|
|
elif T is seq:
|
|
case n.kind
|
|
of TomlKind.Array:
|
|
result = n.arrayVal
|
|
of TomlKind.Tables:
|
|
result = n.tablesVal
|
|
of TomlKind.Table, TomlKind.InlineTable:
|
|
for x in values(n.tableVal):
|
|
result.add x
|
|
else: discard
|
|
elif T is array:
|
|
case n.kind
|
|
of TomlKind.Array:
|
|
for i, x in n.arrayVal:
|
|
result[i] = x
|
|
of TomlKind.Tables:
|
|
for i, x in n.tablesVal:
|
|
result[i] = x
|
|
of TomlKind.Table, TomlKind.InlineTable:
|
|
var i = 0
|
|
for x in values(n.tableVal):
|
|
result[i] = x
|
|
inc i
|
|
else: discard
|
|
else:
|
|
const typeName = typetraits.name(T)
|
|
{.error: "Failed to convert to unsupported type: " & typeName & " from TOML".}
|
|
|
|
proc len*(n: TomlValueRef): int =
|
|
## If `n` is a `TomlKind.Array`, it returns the number of elements.
|
|
## If `n` is a `TomlKind.Table`, it returns the number of pairs.
|
|
## Else it returns 0.
|
|
case n.kind
|
|
of TomlKind.Array: result = n.arrayVal.len
|
|
of TomlKind.Table: result = n.tableVal.len
|
|
else: discard
|
|
|
|
proc `[]`*(node: TomlValueRef, name: string): TomlValueRef {.inline.} =
|
|
## Gets a field from a `TomlKind.Table`, which must not be nil.
|
|
## If the value at `name` does not exist, raises KeyError.
|
|
assert(not isNil(node))
|
|
assert(node.kind == TomlKind.Table)
|
|
node.tableVal[name]
|
|
|
|
proc `[]`*(node: TomlValueRef, name: string, T: type): T {.inline.} =
|
|
node[name].innerValue(T)
|
|
|
|
proc `[]`*(node: TomlValueRef, index: int): TomlValueRef {.inline.} =
|
|
## Gets the node at `index` in an Array. Result is undefined if `index`
|
|
## is out of bounds, but as long as array bound checks are enabled it will
|
|
## result in an exception.
|
|
assert(not isNil(node))
|
|
assert(node.kind == TomlKind.Array)
|
|
node.arrayVal[index]
|
|
|
|
proc `[]`*(node: TomlValueRef, index: int, T: type): T {.inline.} =
|
|
node[index].innerValue(T)
|
|
|
|
proc hasKey*(node: TomlValueRef, key: string): bool =
|
|
## Checks if `key` exists in `node`.
|
|
assert(node.kind == TomlKind.Table)
|
|
result = node.tableVal.hasKey(key)
|
|
|
|
proc contains*(node: TomlValueRef, key: string): bool =
|
|
## Checks if `key` exists in `node`.
|
|
assert(node.kind == TomlKind.Table)
|
|
node.tableVal.hasKey(key)
|
|
|
|
proc contains*(node: TomlValueRef, val: TomlValueRef): bool =
|
|
## Checks if `val` exists in array `node`.
|
|
assert(node.kind == TomlKind.Array)
|
|
find(node.arrayVal, val) >= 0
|
|
|
|
proc `[]=`*(obj: TomlValueRef, key: string, val: TomlValueRef) {.inline.} =
|
|
## Sets a field from a `TomlKind.Table`.
|
|
assert(obj.kind == TomlKind.Table)
|
|
obj.tableVal[key] = val
|
|
|
|
proc `{}`*(node: TomlValueRef, keys: varargs[string]): TomlValueRef =
|
|
## Traverses the node and gets the given value. If any of the
|
|
## keys do not exist, returns ``nil``. Also returns ``nil`` if one of the
|
|
## intermediate data structures is not an object.
|
|
result = node
|
|
for key in keys:
|
|
if isNil(result) or result.kind != TomlKind.Table:
|
|
return nil
|
|
result = result.tableVal.getOrDefault(key)
|
|
|
|
proc getOrDefault*(node: TomlValueRef, key: string): TomlValueRef =
|
|
## Gets a field from a `node`. If `node` is nil or not an object or
|
|
## value at `key` does not exist, returns nil
|
|
if not isNil(node) and node.kind == TomlKind.Table:
|
|
result = node.tableVal.getOrDefault(key)
|
|
|
|
proc `{}=`*(node: TomlValueRef, keys: varargs[string], value: TomlValueRef) =
|
|
## Traverses the node and tries to set the value at the given location
|
|
## to ``value``. If any of the keys are missing, they are added.
|
|
var node = node
|
|
for i in 0..(keys.len-2):
|
|
if not node.hasKey(keys[i]):
|
|
node[keys[i]] = emptyTable()
|
|
node = node[keys[i]]
|
|
node[keys[keys.len-1]] = value
|
|
|
|
proc delete*(obj: TomlValueRef, key: string) =
|
|
## Deletes ``obj[key]``.
|
|
assert(obj.kind == TomlKind.Table)
|
|
if not obj.tableVal.hasKey(key):
|
|
raise newException(IndexError, "key not in object")
|
|
obj.tableVal.del(key)
|
|
|
|
proc copy*(p: TomlValueRef): TomlValueRef
|
|
|
|
proc copy*(p: TomlTableRef): TomlTableRef =
|
|
result = TomlTableRef.new
|
|
for key, val in pairs(p):
|
|
result[key] = copy(val)
|
|
|
|
proc copy(p: TomlValueRef): TomlValueRef =
|
|
## Performs a deep copy of `p`.
|
|
case p.kind
|
|
of TomlKind.String:
|
|
result = TomlValueRef(
|
|
kind: TomlKind.String,
|
|
stringVal: p.stringVal
|
|
)
|
|
of TomlKind.Int:
|
|
result = TomlValueRef(
|
|
kind: TomlKind.Int,
|
|
intVal: p.intVal
|
|
)
|
|
of TomlKind.Float:
|
|
result = TomlValueRef(
|
|
kind: TomlKind.Float,
|
|
floatVal: p.floatVal
|
|
)
|
|
of TomlKind.Bool:
|
|
result = TomlValueRef(
|
|
kind: TomlKind.Bool,
|
|
boolVal: p.boolVal
|
|
)
|
|
of TomlKind.Table, TomlKind.InlineTable:
|
|
result = TomlValueRef(kind: p.kind)
|
|
result.tableVal = copy(p.tableVal)
|
|
of TomlKind.Array:
|
|
result = TomlValueRef(kind: TomlKind.Array)
|
|
for x in items(p.arrayVal):
|
|
result.arrayVal.add copy(x)
|
|
of TomlKind.DateTime:
|
|
result = TomlValueRef(kind: TomlKind.DateTime)
|
|
result.dateTime = p.dateTime
|
|
of TomlKind.Tables:
|
|
result = TomlValueRef(kind: TomlKind.Tables)
|
|
for x in items(p.tablesVal):
|
|
result.tablesVal.add copy(x)
|