simplify key api

This commit is contained in:
Dmitriy Ryajov 2022-09-10 13:50:05 -06:00
parent 2769ce1de2
commit ed6842b743
No known key found for this signature in database
GPG Key ID: DA8C680CE7C657A4
2 changed files with 192 additions and 516 deletions

View File

@ -15,11 +15,11 @@ push: {.upraises: [].}
type
Namespace* = object
field: ?string
value: string
field*: string
value*: string
Key* = object
namespaces: seq[Namespace]
namespaces*: seq[Namespace]
const
delimiter = ":"
@ -32,11 +32,8 @@ proc init*(
T: type Namespace,
field, value: string): ?!T =
if value == "":
return failure "value string must not be empty"
if value.strip == "":
return failure "value string must not be all whitespace"
return failure "value string must not be all whitespace or empty"
if value.contains(delimiter):
return failure "value string must not contain delimiter \"" &
@ -58,19 +55,11 @@ proc init*(
return failure "field string must not contain separator \"" &
separator & "\""
success T(field: field.some, value: value)
else:
success T(field: string.none, value: value)
proc init*(
T: type Namespace,
id: string): ?!T =
if id == "":
return failure "id string must not be empty"
success T(field: field, value: value)
proc init*(T: type Namespace, id: string): ?!T =
if id.strip == "":
return failure "id string must not be all whitespace"
return failure "id string must not be all whitespace or empty"
if id.contains(separator):
return failure "id string must not contain separator \"" & separator & "\""
@ -79,98 +68,45 @@ proc init*(
return failure "value in id string \"[field]" & delimiter &
"[value]\" must not be empty"
let
s = id.split(delimiter)
if s.len > 2:
if id.count(delimiter) > 1:
return failure "id string must not contain more than one delimiter \"" &
delimiter & "\""
var
field: ?string
value: string
let
(field, value) = block:
let parts = id.split(delimiter)
if parts.len > 1:
(parts[0], parts[^1])
else:
("", parts[^1])
if s.len == 1:
value = s[0]
else:
value = s[1]
if value == "":
return failure "value in id string \"[field]" & delimiter &
"[value]\" must not be empty"
if value.strip == "":
return failure "value in id string \"[field]" & delimiter &
"[value]\" must not be all whitespace"
else:
let
f = s[0]
if f != "":
if f.strip == "":
return failure "field in id string \"[field]" & delimiter &
"[value]\" must not be all whitespace"
else:
field = f.some
success T(field: field, value: value)
proc value*(self: Namespace): string =
self.value
proc field*(self: Namespace): ?string =
self.field
proc `type`*(self: Namespace): ?string =
self.field
proc kind*(self: Namespace): ?string =
self.`type`
T.init(field, value)
proc id*(self: Namespace): string =
if field =? self.field: field & delimiter & self.value
else: self.value
if self.field.len > 0:
self.field & delimiter & self.value
else:
self.value
proc `$`*(namespace: Namespace): string =
"Namespace(" & namespace.id & ")"
proc init*(
T: type Key,
namespaces: varargs[Namespace]): ?!T =
proc init*(T: type Key, namespaces: varargs[Namespace]): ?!T =
if namespaces.len == 0:
failure "namespaces must contain at least one Namespace"
else:
success T(namespaces: @namespaces)
proc init*(
T: type Key,
namespaces: varargs[string]): ?!T =
proc init*(T: type Key, namespaces: varargs[string]): ?!T =
if namespaces.len == 0:
failure "namespaces must contain at least one Namespace id string"
else:
var
nss: seq[Namespace]
for s in namespaces:
let
nsRes = Namespace.init(s)
if nsRes.isErr:
return failure "namespaces contains an invalid Namespace: " &
nsRes.error.msg
nss.add nsRes.get
success T(namespaces: nss)
proc init*(
T: type Key,
id: string): ?!T =
success T(
namespaces: namespaces.mapIt(
?Namespace.init(it)
))
proc init*(T: type Key, id: string): ?!T =
if id == "":
return failure "id string must contain at least one Namespace"
@ -184,17 +120,7 @@ proc init*(
return failure "id string must not contain only one or more separator " &
"\"" & separator & "\""
let
keyRes = Key.init(nsStrs)
if keyRes.isErr:
return failure "id string contains an invalid Namespace:" &
keyRes.error.msg.split(":")[1..^1].join("").replace("\"\"", "\":\"")
keyRes
proc namespaces*(self: Key): seq[Namespace] =
self.namespaces
Key.init(nsStrs)
proc list*(self: Key): seq[Namespace] =
self.namespaces
@ -202,22 +128,15 @@ proc list*(self: Key): seq[Namespace] =
proc random*(T: type Key): string =
$genOid()
template `[]`*(
key: Key,
x: auto): auto =
template `[]`*(key: Key, x: auto): auto =
key.namespaces[x]
proc len*(self: Key): int =
self.namespaces.len
iterator items*(key: Key): Namespace =
var
i = 0
while i < key.len:
yield key[i]
inc i
for k in key.namespaces:
yield k
proc reversed*(self: Key): Key =
Key(namespaces: self.namespaces.reversed)
@ -226,55 +145,15 @@ proc reverse*(self: Key): Key =
self.reversed
proc name*(self: Key): string =
self[^1].value
if self.len > 0:
return self[^1].value
proc `type`*(self: Key): ?string =
self[^1].field
proc `type`*(self: Key): string =
if self.len > 0:
return self[^1].field
proc kind*(self: Key): ?string =
self.`type`
proc instance*(
self: Key,
value: Namespace): Key =
let
last = self[^1]
inst =
if last.field.isSome:
@[Namespace(field: last.field, value: value.value)]
else:
@[Namespace(field: last.value.some, value: value.value)]
namespaces =
if self.namespaces.len == 1:
inst
else:
self.namespaces[0..^2] & inst
Key(namespaces: namespaces)
proc instance*(self, value: Key): Key =
self.instance(value[^1])
proc instance*(self, value: Namespace): Key =
Key(namespaces: @[self]).instance(value)
proc instance*(
self: Namespace,
value: Key): Key =
self.instance(value[^1])
proc instance*(
self: Key,
id: string): ?!Key =
without key =? Key.init(id), e:
return failure e
success self.instance(key)
proc id*(self: Key): string =
separator & self.namespaces.mapIt(it.id).join(separator)
proc isTopLevel*(self: Key): bool =
self.len == 1
@ -285,43 +164,22 @@ proc parent*(self: Key): ?!Key =
else:
success Key(namespaces: self.namespaces[0..^2])
proc parent*(self: ?!Key): ?!Key =
let
key = ? self
key.parent
proc path*(self: Key): ?!Key =
let
parent = ? self.parent
without kind =? self[^1].kind:
if self[^1].field == "":
return success parent
success Key(namespaces: parent.namespaces & @[Namespace(value: kind)])
proc path*(self: ?!Key): ?!Key =
let
key = ? self
key.path
proc child*(
self: Key,
ns: Namespace): Key =
success Key(namespaces: parent.namespaces & @[Namespace(value: self[^1].field)])
proc child*(self: Key, ns: Namespace): Key =
Key(namespaces: self.namespaces & @[ns])
proc `/`*(
self: Key,
ns: Namespace): Key =
proc `/`*(self: Key, ns: Namespace): Key =
self.child(ns)
proc child*(
self: Key,
namespaces: varargs[Namespace]): Key =
proc child*(self: Key, namespaces: varargs[Namespace]): Key =
Key(namespaces: self.namespaces & @namespaces)
proc child*(self, key: Key): Key =
@ -330,34 +188,13 @@ proc child*(self, key: Key): Key =
proc `/`*(self, key: Key): Key =
self.child(key)
proc child*(
self: Key,
keys: varargs[Key]): Key =
proc child*(self: Key, keys: varargs[Key]): Key =
Key(namespaces: self.namespaces & concat(keys.mapIt(it.namespaces)))
proc child*(
self: Key,
ids: varargs[string]): ?!Key =
let
ids = ids.filterIt(it != "")
var
keys: seq[Key]
for id in ids:
let
key = ? Key.init(id)
keys.add key
success self.child(keys)
proc `/`*(
self: Key,
id: string): ?!Key =
proc child*(self: Key, ids: varargs[string]): ?!Key =
success self.child(ids.filterIt(it != "").mapIt( ?Key.init(it) ))
proc `/`*(self: Key, id: string): ?!Key =
self.child(id)
proc isAncestorOf*(self, other: Key): bool =
@ -367,8 +204,5 @@ proc isAncestorOf*(self, other: Key): bool =
proc isDescendantOf*(self, other: Key): bool =
other.isAncestorOf(self)
proc id*(self: Key): string =
separator & self.namespaces.mapIt(it.id).join(separator)
proc `$`*(key: Key): string =
"Key(" & key.id & ")"

View File

@ -1,310 +1,179 @@
import std/options
import pkg/stew/results
import pkg/unittest2
import pkg/questionable
import pkg/questionable/results
import ../../datastore/key
suite "Namespace":
test "init":
var
nsRes: Result[Namespace, ref CatchableError]
test "init failure":
check:
Namespace.init("a", "").isFailure
Namespace.init("a", " ").isFailure
Namespace.init("a", ":").isFailure
Namespace.init("a", "/").isFailure
Namespace.init(":", "b").isFailure
Namespace.init("/", "b").isFailure
Namespace.init(" ", "b").isFailure
Namespace.init("").isFailure
Namespace.init(" ").isFailure
Namespace.init("/").isFailure
Namespace.init(":").isFailure
Namespace.init("a:b:c").isFailure
Namespace.init("a:").isFailure
Namespace.init("a: ").isFailure
Namespace.init(" :b").isFailure
nsRes = Namespace.init("a", "")
check: nsRes.isErr
nsRes = Namespace.init("a", " ")
check: nsRes.isErr
nsRes = Namespace.init("a", ":")
check: nsRes.isErr
nsRes = Namespace.init("a", "/")
check: nsRes.isErr
nsRes = Namespace.init(":", "b")
check: nsRes.isErr
nsRes = Namespace.init("/", "b")
check: nsRes.isErr
nsRes = Namespace.init("", "b")
check: nsRes.isOk
nsRes = Namespace.init(" ", "b")
check: nsRes.isErr
nsRes = Namespace.init("a", "b")
check: nsRes.isOk
nsRes = Namespace.init("")
check: nsRes.isErr
nsRes = Namespace.init(" ")
check: nsRes.isErr
nsRes = Namespace.init("/")
check: nsRes.isErr
nsRes = Namespace.init(":")
check: nsRes.isErr
nsRes = Namespace.init("a:b:c")
check: nsRes.isErr
nsRes = Namespace.init("a")
check: nsRes.isOk
nsRes = Namespace.init("a:")
check: nsRes.isErr
nsRes = Namespace.init("a: ")
check: nsRes.isErr
nsRes = Namespace.init(" :b")
check: nsRes.isErr
nsRes = Namespace.init("a:b")
check: nsRes.isOk
nsRes = Namespace.init(":b")
check: nsRes.isOk
test "init success":
check:
Namespace.init("", "b").isSuccess
Namespace.init("a", "b").isSuccess
Namespace.init("a").isSuccess
Namespace.init("a:b").isSuccess
Namespace.init(":b").isSuccess
test "accessors":
var
ns: Namespace
ns = Namespace.init("", "b").get
ns = Namespace.init("", "b").tryGet()
check:
ns.value == "b"
ns.field.isNone
ns.field == ""
ns = Namespace.init("a", "b").get
ns = Namespace.init("a", "b").tryGet()
check:
ns.value == "b"
ns.field.isSome and ns.field.get == "a"
ns.field != "" and ns.field == "a"
ns = Namespace.init(":b").get
ns = Namespace.init(":b").tryGet()
check:
ns.value == "b"
ns.field.isNone
ns.field == ""
ns = Namespace.init("a:b").get
ns = Namespace.init("a:b").tryGet()
check:
ns.value == "b"
ns.field.isSome and ns.field.get == "a"
check:
ns.`type`.get == ns.field.get
ns.kind.get == ns.field.get
ns.field == "a"
test "equality":
check:
Namespace.init("a").get == Namespace.init("a").get
Namespace.init("a").get != Namespace.init("b").get
Namespace.init("", "b").get == Namespace.init("", "b").get
Namespace.init("", "b").get == Namespace.init("b").get
Namespace.init(":b").get == Namespace.init("b").get
Namespace.init("", "b").get != Namespace.init("", "a").get
Namespace.init("", "b").get != Namespace.init("a").get
Namespace.init(":b").get != Namespace.init("a").get
Namespace.init("a", "b").get == Namespace.init("a", "b").get
Namespace.init("a", "b").get == Namespace.init("a:b").get
Namespace.init("a:b").get == Namespace.init("a:b").get
Namespace.init("a", "b").get != Namespace.init("b", "a").get
Namespace.init("a", "b").get != Namespace.init("b:a").get
Namespace.init("a:b").get != Namespace.init("b:a").get
Namespace.init("a").get != Namespace.init("a:b").get
Namespace.init("a").tryGet() == Namespace.init("a").tryGet()
Namespace.init("a").tryGet() != Namespace.init("b").tryGet()
Namespace.init("", "b").tryGet() == Namespace.init("", "b").tryGet()
Namespace.init("", "b").tryGet() == Namespace.init("b").tryGet()
Namespace.init(":b").tryGet() == Namespace.init("b").tryGet()
Namespace.init("", "b").tryGet() != Namespace.init("", "a").tryGet()
Namespace.init("", "b").tryGet() != Namespace.init("a").tryGet()
Namespace.init(":b").tryGet() != Namespace.init("a").tryGet()
Namespace.init("a", "b").tryGet() == Namespace.init("a", "b").tryGet()
Namespace.init("a", "b").tryGet() == Namespace.init("a:b").tryGet()
Namespace.init("a:b").tryGet() == Namespace.init("a:b").tryGet()
Namespace.init("a", "b").tryGet() != Namespace.init("b", "a").tryGet()
Namespace.init("a", "b").tryGet() != Namespace.init("b:a").tryGet()
Namespace.init("a:b").tryGet() != Namespace.init("b:a").tryGet()
Namespace.init("a").tryGet() != Namespace.init("a:b").tryGet()
test "serialization":
var
ns: Namespace
ns = Namespace.init(":b").get
ns = Namespace.init(":b").tryGet()
check:
ns.id == "b"
$ns == "Namespace(" & ns.id & ")"
ns = Namespace.init("a:b").get
ns = Namespace.init("a:b").tryGet()
check:
ns.id == "a:b"
$ns == "Namespace(" & ns.id & ")"
suite "Key":
test "init":
var
keyRes: Result[Key, ref CatchableError]
nss: seq[Namespace]
test "init failure":
check:
Key.init("", "").isFailure
Key.init(@[""]).isFailure
Key.init(@[":"]).isFailure
Key.init(@["/"]).isFailure
Key.init("").isFailure
Key.init(" ").isFailure
Key.init("/").isFailure
Key.init("///").isFailure
Key.init(":").isFailure
Key.init("::").isFailure
Key.init("a:").isFailure
Key.init("a:b/c:").isFailure
keyRes = Key.init(nss)
check: keyRes.isErr
nss = @[Namespace.init("a").get]
keyRes = Key.init(nss)
check: keyRes.isOk
var
nsStrs: seq[string]
keyRes = Key.init(nsStrs)
check: keyRes.isErr
nsStrs = @[":"]
keyRes = Key.init(nsStrs)
check: keyRes.isErr
nsStrs = @["/"]
keyRes = Key.init(nsStrs)
check: keyRes.isErr
nsStrs = @["a:b"]
keyRes = Key.init(nsStrs)
check: keyRes.isOk
keyRes = Key.init("")
check: keyRes.isErr
keyRes = Key.init(" ")
check: keyRes.isErr
keyRes = Key.init("/")
check: keyRes.isErr
keyRes = Key.init("///")
check: keyRes.isErr
keyRes = Key.init(":")
check: keyRes.isErr
keyRes = Key.init("::")
check: keyRes.isErr
keyRes = Key.init("a:")
check: keyRes.isErr
keyRes = Key.init("a:b/c:")
check: keyRes.isErr
keyRes = Key.init(":b")
check: keyRes.isOk
keyRes = Key.init("a:b")
check: keyRes.isOk
keyRes = Key.init("a:b/c")
check: keyRes.isOk
keyRes = Key.init("a:b/:c")
check: keyRes.isOk
keyRes = Key.init("/a:b/c/")
check: keyRes.isOk
keyRes = Key.init("///a:b///c///")
check: keyRes.isOk
test "init success":
check:
Key.init(Namespace.init("a").tryGet()).isSuccess
Key.init(@["a:b"]).isSuccess
Key.init(":b").isSuccess
Key.init("a:b").isSuccess
Key.init("a:b/c").isSuccess
Key.init("a:b/:c").isSuccess
Key.init("/a:b/c/").isSuccess
Key.init("///a:b///c///").isSuccess
test "accessors":
let
key = Key.init("/a:b/c/d:e").get
key = Key.init("/a:b/c/d:e").tryGet()
check:
key.namespaces == @[
Namespace.init("a:b").get,
Namespace.init("c").get,
Namespace.init("d:e").get
Namespace.init("a:b").tryGet(),
Namespace.init("c").tryGet(),
Namespace.init("d:e").tryGet()
]
key.list == key.namespaces
test "equality":
check:
Key.init(Namespace.init("a:b").get, Namespace.init("c").get).get == Key.init("a:b/c").get
Key.init("a:b", "c").get == Key.init("a:b/c").get
Key.init("a:b/c").get == Key.init("a:b/c").get
Key.init(Namespace.init("a:b").get, Namespace.init("c").get).get != Key.init("c:b/a").get
Key.init("a:b", "c").get != Key.init("c:b/a").get
Key.init("a:b/c").get != Key.init("c:b/a").get
Key.init("a:b/c").get == Key.init("/a:b/c/").get
Key.init("a:b/c").get == Key.init("///a:b///c///").get
Key.init("a:b/c").get != Key.init("///a:b///d///").get
Key.init("a").get != Key.init("a:b").get
Key.init("a").get != Key.init("a/b").get
Key.init("a/b/c").get != Key.init("a/b").get
Key.init("a:X/b/c").get == Key.init("a:X/b/c").get
Key.init("a/b:X/c").get == Key.init("a/b:X/c").get
Key.init("a/b/c:X").get == Key.init("a/b/c:X").get
Key.init("a:X/b/c:X").get == Key.init("a:X/b/c:X").get
Key.init("a:X/b:X/c").get == Key.init("a:X/b:X/c").get
Key.init("a/b:X/c:X").get == Key.init("a/b:X/c:X").get
Key.init("a:X/b:X/c:X").get == Key.init("a:X/b:X/c:X").get
Key.init("a/b/c").get != Key.init("a:X/b/c").get
Key.init("a/b/c").get != Key.init("a/b:X/c").get
Key.init("a/b/c").get != Key.init("a/b/c:X").get
Key.init("a/b/c").get != Key.init("a:X/b/c:X").get
Key.init("a/b/c").get != Key.init("a:X/b:X/c").get
Key.init("a/b/c").get != Key.init("a/b:X/c:X").get
Key.init("a/b/c").get != Key.init("a:X/b:X/c:X").get
Key.init(Namespace.init("a:b").tryGet(), Namespace.init("c").tryGet()).tryGet() == Key.init("a:b/c").tryGet()
Key.init("a:b", "c").tryGet() == Key.init("a:b/c").tryGet()
Key.init("a:b/c").tryGet() == Key.init("a:b/c").tryGet()
Key.init(Namespace.init("a:b").tryGet(), Namespace.init("c").tryGet()).tryGet() != Key.init("c:b/a").tryGet()
Key.init("a:b", "c").tryGet() != Key.init("c:b/a").tryGet()
Key.init("a:b/c").tryGet() != Key.init("c:b/a").tryGet()
Key.init("a:b/c").tryGet() == Key.init("/a:b/c/").tryGet()
Key.init("a:b/c").tryGet() == Key.init("///a:b///c///").tryGet()
Key.init("a:b/c").tryGet() != Key.init("///a:b///d///").tryGet()
Key.init("a").tryGet() != Key.init("a:b").tryGet()
Key.init("a").tryGet() != Key.init("a/b").tryGet()
Key.init("a/b/c").tryGet() != Key.init("a/b").tryGet()
Key.init("a:X/b/c").tryGet() == Key.init("a:X/b/c").tryGet()
Key.init("a/b:X/c").tryGet() == Key.init("a/b:X/c").tryGet()
Key.init("a/b/c:X").tryGet() == Key.init("a/b/c:X").tryGet()
Key.init("a:X/b/c:X").tryGet() == Key.init("a:X/b/c:X").tryGet()
Key.init("a:X/b:X/c").tryGet() == Key.init("a:X/b:X/c").tryGet()
Key.init("a/b:X/c:X").tryGet() == Key.init("a/b:X/c:X").tryGet()
Key.init("a:X/b:X/c:X").tryGet() == Key.init("a:X/b:X/c:X").tryGet()
Key.init("a/b/c").tryGet() != Key.init("a:X/b/c").tryGet()
Key.init("a/b/c").tryGet() != Key.init("a/b:X/c").tryGet()
Key.init("a/b/c").tryGet() != Key.init("a/b/c:X").tryGet()
Key.init("a/b/c").tryGet() != Key.init("a:X/b/c:X").tryGet()
Key.init("a/b/c").tryGet() != Key.init("a:X/b:X/c").tryGet()
Key.init("a/b/c").tryGet() != Key.init("a/b:X/c:X").tryGet()
Key.init("a/b/c").tryGet() != Key.init("a:X/b:X/c:X").tryGet()
test "helpers":
check: Key.random.len == 24
let
key = Key.init("/a:b/c/d:e").get
key = Key.init("/a:b/c/d:e").tryGet()
check:
key[1] == Namespace.init("c").get
key[1..^1] == @[Namespace.init("c").get, Namespace.init("d:e").get]
key[^1] == Namespace.init("d:e").get
key[1] == Namespace.init("c").tryGet()
key[1..^1] == @[Namespace.init("c").tryGet(), Namespace.init("d:e").tryGet()]
key[^1] == Namespace.init("d:e").tryGet()
check: key.len == key.namespaces.len
@ -316,16 +185,16 @@ suite "Key":
check:
nss == @[
Namespace.init("a:b").get,
Namespace.init("c").get,
Namespace.init("d:e").get
Namespace.init("a:b").tryGet(),
Namespace.init("c").tryGet(),
Namespace.init("d:e").tryGet()
]
check:
key.reversed.namespaces == @[
Namespace.init("d:e").get,
Namespace.init("c").get,
Namespace.init("a:b").get
Namespace.init("d:e").tryGet(),
Namespace.init("c").tryGet(),
Namespace.init("a:b").tryGet()
]
key.reverse == key.reversed
@ -333,95 +202,68 @@ suite "Key":
check: key.name == "e"
check:
key.`type` == key[^1].`type`
key.kind == key.`type`
Key.init(":b").tryGet().isTopLevel
not Key.init(":b/c").tryGet().isTopLevel
check:
key.instance(Namespace.init("f:g").get) == Key.init("a:b/c/d:g").get
Key.init("a:b").get.instance(Namespace.init(":c").get) == Key.init("a:c").get
Key.init(":b").get.instance(Namespace.init(":c").get) == Key.init("b:c").get
Key.init(":b").get.instance(key) == Key.init("b:e").get
Namespace.init("a:b").get.instance(Namespace.init("c").get) == Key.init("a:c").get
Namespace.init(":b").get.instance(Namespace.init("c").get) == Key.init("b:c").get
Namespace.init("a:b").get.instance(key) == Key.init("a:e").get
Namespace.init(":b").get.instance(key) == Key.init("b:e").get
Key.init(":b").get.instance("").isErr
Key.init(":b").get.instance(":").isErr
Key.init(":b").get.instance("/").isErr
Key.init(":b").get.instance("//").isErr
Key.init(":b").get.instance("///").isErr
Key.init(":b").get.instance("a").get == Key.init("b:a").get
Key.init(":b").get.instance(":b").get == Key.init("b:b").get
Key.init(":b").get.instance("a:b").get == Key.init("b:b").get
Key.init(":b").get.instance("/a:b/c/d:e").get == Key.init("b:e").get
Key.init("a:b").get.instance("a").get == Key.init("a:a").get
Key.init("a:b").get.instance(":b").get == Key.init("a:b").get
Key.init("a:b").get.instance("a:b").get == Key.init("a:b").get
Key.init("a:b").get.instance("/a:b/c/d:e").get == Key.init("a:e").get
Key.init(":b").tryGet().parent.isFailure
Key.init(":b").tryGet().parent.isFailure
key.parent.tryGet() == Key.init("a:b/c").tryGet()
key.parent.?parent.tryGet() == Key.init("a:b").tryGet()
key.parent.?parent.?parent.isFailure
check:
Key.init(":b").get.isTopLevel
not Key.init(":b/c").get.isTopLevel
key.parent.?path.tryGet() == Key.init("a:b").tryGet()
key.path.tryGet() == Key.init("a:b/c/d").tryGet()
Key.init("a:b/c").?path.tryGet() == Key.init("a:b").tryGet()
Key.init("a:b/c/d:e").?path.tryGet() == Key.init("a:b/c/d").tryGet()
check:
Key.init(":b").get.parent.isErr
Key.init(":b").parent.isErr
key.parent.get == Key.init("a:b/c").get
key.parent.parent.get == Key.init("a:b").get
key.parent.parent.parent.isErr
check: key.child(Namespace.init("f:g").tryGet()) == Key.init("a:b/c/d:e/f:g").tryGet()
check:
key.parent.get.path.get == Key.init("a:b").get
key.path.get == Key.init("a:b/c/d").get
Key.init("a:b/c").path.get == Key.init("a:b").get
Key.init("a:b/c/d:e").path.get == Key.init("a:b/c/d").get
check: key.child(Namespace.init("f:g").get) == Key.init("a:b/c/d:e/f:g").get
check: key / Namespace.init("f:g").get == Key.init("a:b/c/d:e/f:g").get
check: key / Namespace.init("f:g").tryGet() == Key.init("a:b/c/d:e/f:g").tryGet()
var
emptyNss: seq[Namespace]
check:
key.child(emptyNss) == key
key.child(Namespace.init("f:g").get, Namespace.init("h:i").get) ==
Key.init("a:b/c/d:e/f:g/h:i").get
key.child(Namespace.init("f:g").tryGet(), Namespace.init("h:i").tryGet()) ==
Key.init("a:b/c/d:e/f:g/h:i").tryGet()
check:
key.child(Key.init("f:g").get) == Key.init("a:b/c/d:e/f:g").get
key / Key.init("f:g").get == Key.init("a:b/c/d:e/f:g").get
key.child(Key.init("f:g").tryGet()) == Key.init("a:b/c/d:e/f:g").tryGet()
key / Key.init("f:g").tryGet() == Key.init("a:b/c/d:e/f:g").tryGet()
var
emptyKeys: seq[Key]
check:
key.child(emptyKeys) == key
key.child(Key.init("f:g").get, Key.init("h:i").get) ==
Key.init("a:b/c/d:e/f:g/h:i").get
key.child(Key.init("f:g").tryGet(), Key.init("h:i").tryGet()) ==
Key.init("a:b/c/d:e/f:g/h:i").tryGet()
check:
key.child("f:g", ":::").isErr
key.child("f:g", "h:i").get == Key.init("a:b/c/d:e/f:g/h:i").get
key.child("").get == key
key.child("", "", "").get == key
key.child("f:g", ":::").isFailure
key.child("f:g", "h:i").tryGet() == Key.init("a:b/c/d:e/f:g/h:i").tryGet()
key.child("").tryGet() == key
key.child("", "", "").tryGet() == key
check:
(key / "").get == key
(key / "f:g").get == Key.init("a:b/c/d:e/f:g").get
(key / "").tryGet() == key
(key / "f:g").tryGet() == Key.init("a:b/c/d:e/f:g").tryGet()
check:
not key.isAncestorOf(Key.init("f:g").get)
key.isAncestorOf(key / Key.init("f:g").get)
not key.isAncestorOf(Key.init("f:g").tryGet())
key.isAncestorOf(key / Key.init("f:g").tryGet())
check:
key.isDescendantOf(key.parent.get)
not Key.init("f:g").get.isDescendantOf(key.parent.get)
key.isDescendantOf(key.parent.tryGet())
not Key.init("f:g").tryGet().isDescendantOf(key.parent.tryGet())
test "serialization":
let
idStr = "/a:b/c/d:e"
key = Key.init(idStr).get
key = Key.init(idStr).tryGet()
check:
key.id == idStr