All files / json-crdt/equal index.ts

80.76% Statements 42/52
75.67% Branches 28/37
100% Functions 1/1
97.05% Lines 33/34

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 472x 2x                     2x 4051x 4051x 3561x 3406x 1111x 2295x 1362x 1362x 1362x 1362x 1362x 1362x 1361x 3008x 3008x   1357x 933x 928x 928x 928x 928x 928x 5x 1x 1x 1x 2x 1x 4x 4x      
import {deepEqual} from '@jsonjoy.com/util/lib/json-equal/deepEqual';
import {ArrNode, BinNode, ConNode, type JsonNode, ObjNode, StrNode, ValNode, VecNode} from '../nodes';
 
/**
 * Deeply checks if two JSON nodes have the same schema and values. Does not
 * verify that the CRDT metadata (like timestamps) are the same, only that
 * the structure and values are equal.
 *
 * @param a The first JSON CRDT node.
 * @param b The second JSON CRDT node.
 * @returns True if the schemas and values are equal, false otherwise.
 */
export const equalSchema = <A extends JsonNode<any>>(a: A, b: unknown, compareContent: boolean): b is A => {
  Iif (a === b) return true;
  if (a instanceof ConNode) return b instanceof ConNode && (!compareContent || deepEqual(a.val, b.val));
  else if (a instanceof ValNode) return b instanceof ValNode && equalSchema(a.node(), b.node(), compareContent);
  else if (a instanceof StrNode)
    return b instanceof StrNode && (!compareContent || (a.length() === b.length() && a.view() === b.view()));
  else if (a instanceof ObjNode) {
    Iif (!(b instanceof ObjNode)) return false;
    const keys1 = a.keys;
    const keys2 = b.keys;
    const length1 = keys1.size;
    const length2 = keys2.size;
    if (length1 !== length2) return false;
    for (const key of keys1.keys()) {
      Iif (!keys2.has(key)) return false;
      if (!equalSchema(a.get(key), b.get(key), compareContent)) return false;
    }
    return true;
  } else if (a instanceof ArrNode) {
    Iif (!(b instanceof ArrNode)) return false;
    const length = a.length();
    Iif (length !== b.length()) return false;
    for (let i = 0; i < length; i++) Iif (!equalSchema(a.getNode(i)!, b.getNode(i), compareContent)) return false;
    return true;
  } else if (a instanceof VecNode) {
    Iif (!(b instanceof VecNode)) return false;
    const length = a.length();
    Iif (length !== b.length()) return false;
    for (let i = 0; i < length; i++) Iif (!equalSchema(a.get(i), b.get(i), compareContent)) return false;
    return true;
  } else if (a instanceof BinNode)
    return b instanceof BinNode && (!compareContent || (a.length() === b.length() && deepEqual(a.view(), b.view())));
  return false;
};