jsonld_syntax/compare.rs
1use jstrict::Value;
2
3/// Comparison ignoring the order of array items and object entries.
4pub trait Compare {
5 /// Checks whether the two values are equal, up to the order of array
6 /// items and object entries.
7 ///
8 /// Two arrays are equal when they have the same length and each item of
9 /// one can be paired with a distinct, `compare`-equal item of the other.
10 /// An object containing a duplicate key never compares equal, since such
11 /// a document is not valid JSON-LD.
12 fn compare(&self, other: &Self) -> bool;
13}
14
15impl Compare for Value {
16 fn compare(&self, other: &Self) -> bool {
17 match (self, other) {
18 (Self::Null, Self::Null) => true,
19 (Self::Boolean(a), Self::Boolean(b)) => a == b,
20 (Self::Number(a), Self::Number(b)) => a == b,
21 (Self::String(a), Self::String(b)) => a == b,
22 (Self::Array(a), Self::Array(b)) if a.len() == b.len() => {
23 let mut selected = Vec::new();
24 selected.resize(b.len(), false);
25
26 'next_item: for item in a {
27 for (other, selected) in b.iter().zip(selected.iter_mut()) {
28 if !*selected && item.compare(other) {
29 *selected = true;
30 continue 'next_item;
31 }
32 }
33
34 return false;
35 }
36
37 true
38 }
39 (Self::Object(a), Self::Object(b)) if a.len() == b.len() => {
40 for entry in a {
41 // Duplicate keys mean the document isn't valid JSON-LD;
42 // treat as "not equal".
43 match b.get_unique(&*entry.key) {
44 Ok(Some(value)) => {
45 if !entry.value.compare(value) {
46 return false;
47 }
48 }
49 Ok(None) | Err(_) => return false,
50 }
51 }
52
53 true
54 }
55 _ => false,
56 }
57 }
58}