Add JsonValueRef compare operation (#89)

This commit is contained in:
andri lim 2024-03-20 21:32:43 +07:00 committed by GitHub
parent 7516a92eb8
commit 1ac1d69f95
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 174 additions and 23 deletions

View File

@ -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.}

View File

@ -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