Add JsonValueRef compare operation (#89)
This commit is contained in:
parent
7516a92eb8
commit
1ac1d69f95
|
@ -1,5 +1,5 @@
|
||||||
# json-serialization
|
# json-serialization
|
||||||
# Copyright (c) 2023 Status Research & Development GmbH
|
# Copyright (c) 2023-2024 Status Research & Development GmbH
|
||||||
# Licensed under either of
|
# Licensed under either of
|
||||||
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
|
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
|
||||||
# * MIT license ([LICENSE-MIT](LICENSE-MIT))
|
# * MIT license ([LICENSE-MIT](LICENSE-MIT))
|
||||||
|
@ -79,4 +79,60 @@ proc delete*(obj: JsonValueRef, key: string) =
|
||||||
raise newException(IndexDefect, "key not in object")
|
raise newException(IndexDefect, "key not in object")
|
||||||
obj.objVal.del(key)
|
obj.objVal.del(key)
|
||||||
|
|
||||||
|
func compare*(lhs, rhs: JsonValueRef): bool
|
||||||
|
|
||||||
|
func compareObject(lhs, rhs: JsonValueRef): bool =
|
||||||
|
## assume lhs.len >= rhs.len
|
||||||
|
## null field and no field are treated equals
|
||||||
|
for k, v in lhs.objVal:
|
||||||
|
let rhsVal = rhs.objVal.getOrDefault(k, nil)
|
||||||
|
if rhsVal.isNil:
|
||||||
|
if v.kind != JsonValueKind.Null:
|
||||||
|
return false
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
if not compare(rhsVal, v):
|
||||||
|
return false
|
||||||
|
true
|
||||||
|
|
||||||
|
func compare*(lhs, rhs: JsonValueRef): bool =
|
||||||
|
## The difference between `==` and `compare`
|
||||||
|
## lies in the object comparison. Null field `compare`
|
||||||
|
## to non existent field will return true.
|
||||||
|
## On the other hand, `==` will return false.
|
||||||
|
|
||||||
|
if lhs.isNil and rhs.isNil:
|
||||||
|
return true
|
||||||
|
|
||||||
|
if not lhs.isNil and rhs.isNil:
|
||||||
|
return false
|
||||||
|
|
||||||
|
if lhs.isNil and not rhs.isNil:
|
||||||
|
return false
|
||||||
|
|
||||||
|
if lhs.kind != rhs.kind:
|
||||||
|
return false
|
||||||
|
|
||||||
|
case lhs.kind
|
||||||
|
of JsonValueKind.String:
|
||||||
|
lhs.strVal == rhs.strVal
|
||||||
|
of JsonValueKind.Number:
|
||||||
|
lhs.numVal == rhs.numVal
|
||||||
|
of JsonValueKind.Object:
|
||||||
|
if lhs.objVal.len >= rhs.objVal.len:
|
||||||
|
compareObject(lhs, rhs)
|
||||||
|
else:
|
||||||
|
compareObject(rhs, lhs)
|
||||||
|
of JsonValueKind.Array:
|
||||||
|
if lhs.arrayVal.len != rhs.arrayVal.len:
|
||||||
|
return false
|
||||||
|
for i, x in lhs.arrayVal:
|
||||||
|
if not compare(x, rhs.arrayVal[i]):
|
||||||
|
return false
|
||||||
|
true
|
||||||
|
of JsonValueKind.Bool:
|
||||||
|
lhs.boolVal == rhs.boolVal
|
||||||
|
of JsonValueKind.Null:
|
||||||
|
true
|
||||||
|
|
||||||
{.pop.}
|
{.pop.}
|
||||||
|
|
|
@ -9,35 +9,130 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
unittest2,
|
unittest2,
|
||||||
../json_serialization
|
../json_serialization,
|
||||||
|
../json_serialization/value_ops
|
||||||
|
|
||||||
func jsonBool(x: bool): JsonValueRef[uint64] =
|
func jsonBool(x: bool): JsonValueRef[uint64] =
|
||||||
JsonValueRef[uint64](kind: JsonValueKind.Bool, boolVal: x)
|
JsonValueRef[uint64](kind: JsonValueKind.Bool, boolVal: x)
|
||||||
|
|
||||||
|
func jsonNull(): JsonValueRef[uint64] =
|
||||||
|
JsonValueRef[uint64](kind: JsonValueKind.Null)
|
||||||
|
|
||||||
suite "Test JsonValueRef":
|
suite "Test JsonValueRef":
|
||||||
|
let objA = JsonValueRef[uint64](
|
||||||
|
kind: JsonValueKind.Object,
|
||||||
|
objVal: [
|
||||||
|
("a", jsonBool(true)),
|
||||||
|
].toOrderedTable
|
||||||
|
)
|
||||||
|
|
||||||
|
let objA2 = JsonValueRef[uint64](
|
||||||
|
kind: JsonValueKind.Object,
|
||||||
|
objVal: [
|
||||||
|
("a", jsonBool(true)),
|
||||||
|
].toOrderedTable
|
||||||
|
)
|
||||||
|
|
||||||
|
let objABNull = JsonValueRef[uint64](
|
||||||
|
kind: JsonValueKind.Object,
|
||||||
|
objVal: [
|
||||||
|
("a", jsonBool(true)),
|
||||||
|
("b", jsonNull())
|
||||||
|
].toOrderedTable
|
||||||
|
)
|
||||||
|
|
||||||
|
let objAB = JsonValueRef[uint64](
|
||||||
|
kind: JsonValueKind.Object,
|
||||||
|
objVal: [
|
||||||
|
("a", jsonBool(true)),
|
||||||
|
("b", jsonBool(true))
|
||||||
|
].toOrderedTable
|
||||||
|
)
|
||||||
|
|
||||||
|
let objInArrayA = JsonValueRef[uint64](
|
||||||
|
kind: JsonValueKind.Array,
|
||||||
|
arrayVal: @[
|
||||||
|
objA
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
let objInArrayA2 = JsonValueRef[uint64](
|
||||||
|
kind: JsonValueKind.Array,
|
||||||
|
arrayVal: @[
|
||||||
|
objA2
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
let objInArrayAB = JsonValueRef[uint64](
|
||||||
|
kind: JsonValueKind.Array,
|
||||||
|
arrayVal: @[
|
||||||
|
objAB
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
let objInArrayABNull = JsonValueRef[uint64](
|
||||||
|
kind: JsonValueKind.Array,
|
||||||
|
arrayVal: @[
|
||||||
|
objABNull
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
let objInObjA = JsonValueRef[uint64](
|
||||||
|
kind: JsonValueKind.Object,
|
||||||
|
objVal: [
|
||||||
|
("x", objA)
|
||||||
|
].toOrderedTable
|
||||||
|
)
|
||||||
|
|
||||||
|
let objInObjA2 = JsonValueRef[uint64](
|
||||||
|
kind: JsonValueKind.Object,
|
||||||
|
objVal: [
|
||||||
|
("x", objA2)
|
||||||
|
].toOrderedTable
|
||||||
|
)
|
||||||
|
|
||||||
|
let objInObjAB = JsonValueRef[uint64](
|
||||||
|
kind: JsonValueKind.Object,
|
||||||
|
objVal: [
|
||||||
|
("x", objAB)
|
||||||
|
].toOrderedTable
|
||||||
|
)
|
||||||
|
|
||||||
|
let objInObjABNull = JsonValueRef[uint64](
|
||||||
|
kind: JsonValueKind.Object,
|
||||||
|
objVal: [
|
||||||
|
("x", objABNull)
|
||||||
|
].toOrderedTable
|
||||||
|
)
|
||||||
|
|
||||||
test "Test table keys equality":
|
test "Test table keys equality":
|
||||||
let a = JsonValueRef[uint64](
|
check objA != objAB
|
||||||
kind: JsonValueKind.Object,
|
check objA == objA2
|
||||||
objVal: [
|
check objA != objABNull
|
||||||
("a", jsonBool(true)),
|
check objAB != objABNull
|
||||||
].toOrderedTable
|
|
||||||
)
|
|
||||||
|
|
||||||
let a2 = JsonValueRef[uint64](
|
check objInArrayA != objInArrayAB
|
||||||
kind: JsonValueKind.Object,
|
check objInArrayA != objInArrayABNull
|
||||||
objVal: [
|
check objInArrayA == objInArrayA2
|
||||||
("a", jsonBool(true)),
|
check objInArrayAB != objInArrayABNull
|
||||||
].toOrderedTable
|
|
||||||
)
|
|
||||||
|
|
||||||
let b = JsonValueRef[uint64](
|
check objInObjA != objInObjAB
|
||||||
kind: JsonValueKind.Object,
|
check objInObjA != objInObjABNull
|
||||||
objVal: [
|
check objInObjA == objInObjA2
|
||||||
("a", jsonBool(true)),
|
check objInObjAB != objInObjABNull
|
||||||
("b", jsonBool(true))
|
|
||||||
].toOrderedTable
|
|
||||||
)
|
|
||||||
|
|
||||||
check a != b
|
test "Test compare":
|
||||||
check a == a2
|
check compare(objA, objAB) == false
|
||||||
|
check compare(objA, objA2) == true
|
||||||
|
check compare(objA, objABNull) == true
|
||||||
|
check compare(objAB, objABNull) == false
|
||||||
|
|
||||||
|
check compare(objInArrayA, objInArrayAB) == false
|
||||||
|
check compare(objInArrayA, objInArrayABNull) == true
|
||||||
|
check compare(objInArrayA, objInArrayA2) == true
|
||||||
|
check compare(objInArrayAB, objInArrayABNull) == false
|
||||||
|
|
||||||
|
check compare(objInObjA, objInObjAB) == false
|
||||||
|
check compare(objInObjA, objInObjABNull) == true
|
||||||
|
check compare(objInObjA, objInObjA2) == true
|
||||||
|
check compare(objInObjAB, objInObjABNull) == false
|
||||||
|
|
Loading…
Reference in New Issue