From ed6842b743cde3f331e5d46c852fd26c2854f45d Mon Sep 17 00:00:00 2001 From: Dmitriy Ryajov Date: Sat, 10 Sep 2022 13:50:05 -0600 Subject: [PATCH] simplify key api --- datastore/key.nim | 260 ++++---------------- tests/datastore/test_key.nim | 448 ++++++++++++----------------------- 2 files changed, 192 insertions(+), 516 deletions(-) diff --git a/datastore/key.nim b/datastore/key.nim index 1cd32e0..44d6480 100644 --- a/datastore/key.nim +++ b/datastore/key.nim @@ -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 & ")" diff --git a/tests/datastore/test_key.nim b/tests/datastore/test_key.nim index cc88465..fc7233c 100644 --- a/tests/datastore/test_key.nim +++ b/tests/datastore/test_key.nim @@ -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