mirror of
https://github.com/waku-org/nwaku.git
synced 2025-01-28 23:55:43 +00:00
168 lines
3.9 KiB
Nim
168 lines
3.9 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
|
|
strutils,
|
|
../types,
|
|
serialization/object_serialization,
|
|
faststreams/outputs
|
|
|
|
type
|
|
CodecState* = enum
|
|
TopLevel
|
|
InsideRecord
|
|
ExpectValue
|
|
ArrayOfTable
|
|
|
|
func cmpNimIdent(a, b: string): bool =
|
|
if a.len == 0 and b.len == 0:
|
|
return true
|
|
if a.len == 0 or b.len == 0:
|
|
return false
|
|
if a[0] != b[0]:
|
|
return false
|
|
|
|
var i = 1
|
|
var j = 1
|
|
while true:
|
|
while i < a.len and a[i] == '_': inc i
|
|
while j < b.len and b[j] == '_': inc j
|
|
var aa = if i < a.len: toLowerAscii(a[i]) else: '\0'
|
|
var bb = if j < b.len: toLowerAscii(b[j]) else: '\0'
|
|
let res = ord(aa) - ord(bb)
|
|
if res != 0: return false
|
|
# the characters are identical:
|
|
if i >= a.len:
|
|
# both cursors at the end:
|
|
if j >= b.len: return true
|
|
# not yet at the end of 'b':
|
|
return false
|
|
elif j >= b.len:
|
|
return true
|
|
inc i
|
|
inc j
|
|
|
|
func compare*(a, b: openArray[string], tomlCase: TomlCase): bool =
|
|
case tomlCase
|
|
of TomlCaseSensitive:
|
|
result = a == b
|
|
of TomlCaseInsensitive:
|
|
if a.len != b.len: return false
|
|
for i, x in a:
|
|
if cmpIgnoreCase(x, b[i]) != 0:
|
|
return false
|
|
result = true
|
|
of TomlCaseNim:
|
|
if a.len != b.len: return false
|
|
for i, x in a:
|
|
if not cmpNimIdent(x, b[i]):
|
|
return false
|
|
result = true
|
|
|
|
func compare*(a, b: string, tomlCase: TomlCase): bool =
|
|
case tomlCase
|
|
of TomlCaseSensitive: a == b
|
|
of TomlCaseInsensitive: cmpIgnoreCase(a, b) == 0
|
|
of TomlCaseNim: cmpNimIdent(a, b)
|
|
|
|
proc findFieldReader*(fieldsTable: FieldReadersTable,
|
|
fieldName: string,
|
|
expectedFieldPos: var int, tomlCase: TomlCase): auto =
|
|
for i in expectedFieldPos ..< fieldsTable.len:
|
|
if compare(fieldsTable[i].fieldName, fieldName, tomlCase):
|
|
expectedFieldPos = i + 1
|
|
return fieldsTable[i].reader
|
|
|
|
for i in 0 ..< expectedFieldPos:
|
|
if compare(fieldsTable[i].fieldName, fieldName, tomlCase):
|
|
return fieldsTable[i].reader
|
|
|
|
return nil
|
|
|
|
const
|
|
digits = block:
|
|
var z = ""
|
|
for i in 0..99:
|
|
if i < 10: z.add '0'
|
|
z.add $i
|
|
z
|
|
|
|
maxLen = ($BiggestInt.high).len
|
|
|
|
proc writeInt*(s: OutputStream, x: BiggestInt, len: Positive) =
|
|
var
|
|
num: array[maxLen, char]
|
|
pos = num.len
|
|
numWritten = 0
|
|
|
|
template prepend(c: char) =
|
|
if numWritten < len:
|
|
dec pos
|
|
num[pos] = c
|
|
inc numWritten
|
|
|
|
var val = x
|
|
while val > 99:
|
|
let idx = (val mod 100) * 2
|
|
val = val div 100
|
|
|
|
prepend digits[idx + 1]
|
|
prepend digits[idx]
|
|
|
|
if val < 10:
|
|
prepend char(ord('0') + val)
|
|
else:
|
|
let idx = val * 2
|
|
prepend digits[idx + 1]
|
|
prepend digits[idx]
|
|
|
|
for _ in numWritten ..< len:
|
|
prepend '0'
|
|
|
|
write s, num.toOpenArray(pos, static(num.len - 1))
|
|
|
|
proc toHex*(s: OutputStream, x: BiggestInt, len: Positive) =
|
|
const
|
|
hexChars = "0123456789ABCDEF"
|
|
maxDigits = sizeof(x) * 2
|
|
|
|
var
|
|
hex: array[maxDigits, char]
|
|
pos = hex.len
|
|
n = x
|
|
|
|
template prepend(c: char) =
|
|
dec pos
|
|
hex[pos] = c
|
|
|
|
for _ in 0 ..< len:
|
|
prepend(hexChars[int(n and 0xF)])
|
|
n = n shr 4
|
|
|
|
write s, hex.toOpenArray(pos, static(hex.len - 1))
|
|
|
|
proc emptyTable*(): TomlValueRef =
|
|
TomlValueRef(
|
|
kind: TomlKind.Table,
|
|
tableVal: TomlTableRef.new
|
|
)
|
|
|
|
template uTypeIsRecord*(_: typed): bool =
|
|
false
|
|
|
|
template uTypeIsRecord*[T](_: type seq[T]): bool =
|
|
when T is (object or tuple):
|
|
true
|
|
else:
|
|
false
|
|
|
|
template uTypeIsRecord*[N, T](_: type array[N, T]): bool =
|
|
when T is (object or tuple):
|
|
true
|
|
else:
|
|
false
|