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

View File

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