Skip to content

Commit

Permalink
Add JsonValueRef compare operation (#89)
Browse files Browse the repository at this point in the history
  • Loading branch information
jangko committed Mar 20, 2024
1 parent 7516a92 commit 1ac1d69
Show file tree
Hide file tree
Showing 2 changed files with 177 additions and 26 deletions.
58 changes: 57 additions & 1 deletion json_serialization/value_ops.nim
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# json-serialization
# Copyright (c) 2023 Status Research & Development GmbH
# Copyright (c) 2023-2024 Status Research & Development GmbH
# Licensed under either of
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
# * MIT license ([LICENSE-MIT](LICENSE-MIT))
Expand Down Expand Up @@ -79,4 +79,60 @@ proc delete*(obj: JsonValueRef, key: string) =
raise newException(IndexDefect, "key not in object")
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.}
145 changes: 120 additions & 25 deletions tests/test_valueref.nim
Original file line number Diff line number Diff line change
Expand Up @@ -9,35 +9,130 @@

import
unittest2,
../json_serialization
../json_serialization,
../json_serialization/value_ops

func jsonBool(x: bool): JsonValueRef[uint64] =
JsonValueRef[uint64](kind: JsonValueKind.Bool, boolVal: x)

func jsonNull(): JsonValueRef[uint64] =
JsonValueRef[uint64](kind: JsonValueKind.Null)

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":
let a = JsonValueRef[uint64](
kind: JsonValueKind.Object,
objVal: [
("a", jsonBool(true)),
].toOrderedTable
)

let a2 = JsonValueRef[uint64](
kind: JsonValueKind.Object,
objVal: [
("a", jsonBool(true)),
].toOrderedTable
)

let b = JsonValueRef[uint64](
kind: JsonValueKind.Object,
objVal: [
("a", jsonBool(true)),
("b", jsonBool(true))
].toOrderedTable
)

check a != b
check a == a2
check objA != objAB
check objA == objA2
check objA != objABNull
check objAB != objABNull

check objInArrayA != objInArrayAB
check objInArrayA != objInArrayABNull
check objInArrayA == objInArrayA2
check objInArrayAB != objInArrayABNull

check objInObjA != objInObjAB
check objInObjA != objInObjABNull
check objInObjA == objInObjA2
check objInObjAB != objInObjABNull

test "Test compare":
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

0 comments on commit 1ac1d69

Please sign in to comment.