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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
use json::JsonValue;
use langtag::{LanguageTag, LanguageTagBuf};
use std::collections::HashSet;
pub trait AsJson {
fn as_json(&self) -> JsonValue;
}
impl AsJson for JsonValue {
fn as_json(&self) -> JsonValue {
self.clone()
}
}
impl AsJson for bool {
fn as_json(&self) -> JsonValue {
JsonValue::Boolean(*self)
}
}
impl AsJson for str {
fn as_json(&self) -> JsonValue {
self.into()
}
}
impl AsJson for String {
fn as_json(&self) -> JsonValue {
self.as_str().as_json()
}
}
impl<'a, T: AsRef<[u8]> + ?Sized> AsJson for LanguageTag<'a, T> {
fn as_json(&self) -> JsonValue {
self.as_str().as_json()
}
}
impl<T: AsRef<[u8]>> AsJson for LanguageTagBuf<T> {
fn as_json(&self) -> JsonValue {
self.as_str().as_json()
}
}
impl<T: AsJson> AsJson for [T] {
fn as_json(&self) -> JsonValue {
let mut ary = Vec::with_capacity(self.len());
for item in self {
ary.push(item.as_json())
}
JsonValue::Array(ary)
}
}
impl<T: AsJson> AsJson for Vec<T> {
fn as_json(&self) -> JsonValue {
self.as_slice().as_json()
}
}
impl<T: AsJson> AsJson for HashSet<T> {
fn as_json(&self) -> JsonValue {
let mut ary = Vec::with_capacity(self.len());
for item in self {
ary.push(item.as_json())
}
JsonValue::Array(ary)
}
}
pub fn json_ld_eq(a: &JsonValue, b: &JsonValue) -> bool {
match (a, b) {
(JsonValue::Array(a), JsonValue::Array(b)) if a.len() == b.len() => {
let mut selected = Vec::with_capacity(a.len());
selected.resize(a.len(), false);
'a_items: for item in a {
for i in 0..b.len() {
if !selected[i] && json_ld_eq(&b[i], item) {
selected[i] = true;
continue 'a_items;
}
}
return false;
}
}
(JsonValue::Object(a), JsonValue::Object(b)) if a.len() == b.len() => {
for (key, value_a) in a.iter() {
if let Some(value_b) = b.get(key) {
if key == "@list" {
match (value_a, value_b) {
(JsonValue::Array(item_a), JsonValue::Array(item_b))
if item_a.len() == item_b.len() =>
{
for i in 0..item_a.len() {
if !json_ld_eq(&item_a[i], &item_b[i]) {
return false;
}
}
}
_ => {
if !json_ld_eq(value_a, value_b) {
return false;
}
}
}
} else if !json_ld_eq(value_a, value_b) {
return false;
}
} else {
return false;
}
}
}
_ => return a == b,
}
true
}