Recursive deep equality for arbitrary JavaScript-shaped values.
The crate reproduces the recursive equality algorithm behind Node's
assert.deepEqual and assert.deepStrictEqual as a standalone predicate.
- Loose (the default) compares leaf primitives with coercive
==. So"3"and3are loosely equal,nullandundefinedare loosely equal, and+0and-0are loosely equal. - Strict compares leaf primitives with
Object.is. SoNaNequalsNaN,+0and-0differ, and"3"and3differ.
JavaScript erases type information at runtime. The algorithm branches on each
value's runtime kind: object, array, Map, Set, Date, RegExp,
typed array, ArrayBuffer, and SharedArrayBuffer. Rust keeps that information
in the type system, so the crate models the value space with the Value enum
and branches on it.
use deep_equal::{deep_equal, Options, Value};
let a = Value::Object(vec![
("a".into(), Value::Num(2.0)),
("b".into(), Value::Str("4".into())),
]);
let b = Value::Object(vec![
("a".into(), Value::Num(2.0)),
("b".into(), Value::Num(4.0)),
]);
// Loose: the string "4" coerces to the number 4.
assert!(deep_equal(&a, &b, Options::LOOSE));
// Strict: a string and a number are never equal.
assert!(!deep_equal(&a, &b, Options::STRICT));deep_equal_loose and deep_equal_strict are shorthands for the two modes.
- Recursive object and array equality, order independent over keys.
- Loose and strict leaf coercion: number, string, boolean, null, undefined.
MapandSetequality, order independent, with deep object keys and members and loose primitive coercion.Datetimestamps,RegExpsource and canonical flags.- Typed array brand and byte equality,
ArrayBufferandSharedArrayBufferbyte equality. - Signed zero, NaN, and the infinities.
[dependencies]
deep-equal = "0.1"Licensed under the MIT license.