Skip to main content

jsonld_core/object/
mapped_eq.rs

1use crate::{Id, IndexSet, Indexed, ValidId};
2use std::hash::Hash;
3
4/// Equality up to a renaming of blank node identifiers.
5pub trait MappedEq<T: ?Sized = Self> {
6    /// Blank node identifier type the renaming applies to.
7    type BlankId;
8    /// Structural equality with mapped blank identifiers.
9    ///
10    /// Does not care for metadata.
11    fn mapped_eq<'a, 'b, F: Clone + Fn(&'a Self::BlankId) -> &'b Self::BlankId>(&'a self, other: &T, f: F) -> bool
12    where
13        Self::BlankId: 'a + 'b;
14}
15
16trait UnorderedMappedEq
17where
18    for<'a> &'a Self: IntoIterator<Item = &'a Self::Item>,
19{
20    type Item: MappedEq;
21
22    fn len(&self) -> usize;
23
24    fn unordered_mapped_eq<'a, 'b, F: Clone + Fn(&'a <Self::Item as MappedEq>::BlankId) -> &'b <Self::Item as MappedEq>::BlankId>(
25        &'a self,
26        other: &Self,
27        f: F,
28    ) -> bool
29    where
30        <Self::Item as MappedEq>::BlankId: 'a + 'b,
31    {
32        if self.len() == other.len() {
33            let other_vec: Vec<_> = other.into_iter().collect();
34            let mut selected = Vec::new();
35            selected.resize(other_vec.len(), false);
36
37            'self_items: for item in self {
38                for (i, sel) in selected.iter_mut().enumerate() {
39                    // SAFETY: `i < selected.len() == other_vec.len()`.
40                    let other = unsafe { other_vec.get(i).unwrap_unchecked() };
41                    if !*sel && item.mapped_eq(other, f.clone()) {
42                        *sel = true;
43                        continue 'self_items;
44                    }
45                }
46
47                return false;
48            }
49
50            true
51        } else {
52            false
53        }
54    }
55}
56
57impl<'u, U, T: MappedEq<U>> MappedEq<&'u U> for &T {
58    type BlankId = T::BlankId;
59
60    fn mapped_eq<'a, 'b, F: Clone + Fn(&'a Self::BlankId) -> &'b Self::BlankId>(&'a self, other: &&'u U, f: F) -> bool
61    where
62        Self::BlankId: 'a + 'b,
63    {
64        T::mapped_eq(*self, *other, f)
65    }
66}
67
68impl<T: MappedEq> MappedEq for Option<T> {
69    type BlankId = T::BlankId;
70
71    fn mapped_eq<'a, 'b, F: Clone + Fn(&'a Self::BlankId) -> &'b Self::BlankId>(&'a self, other: &Self, f: F) -> bool
72    where
73        Self::BlankId: 'a + 'b,
74    {
75        match (self, other) {
76            (Some(a), Some(b)) => a.mapped_eq(b, f),
77            (None, None) => true,
78            _ => false,
79        }
80    }
81}
82
83impl<T: MappedEq> UnorderedMappedEq for Vec<T> {
84    type Item = T;
85
86    fn len(&self) -> usize {
87        self.len()
88    }
89}
90
91impl<T: MappedEq> MappedEq for Vec<T> {
92    type BlankId = T::BlankId;
93
94    fn mapped_eq<'a, 'b, F: Clone + Fn(&'a Self::BlankId) -> &'b Self::BlankId>(&'a self, other: &Self, f: F) -> bool
95    where
96        Self::BlankId: 'a + 'b,
97    {
98        self.as_slice().mapped_eq(other.as_slice(), f)
99    }
100}
101
102impl<T: MappedEq> UnorderedMappedEq for [T] {
103    type Item = T;
104
105    fn len(&self) -> usize {
106        self.len()
107    }
108}
109
110impl<T: MappedEq> MappedEq for [T] {
111    type BlankId = T::BlankId;
112
113    fn mapped_eq<'a, 'b, F: Clone + Fn(&'a Self::BlankId) -> &'b Self::BlankId>(&'a self, other: &Self, f: F) -> bool
114    where
115        Self::BlankId: 'a + 'b,
116    {
117        self.len() == other.len() && self.iter().zip(other).all(move |(a, b)| a.mapped_eq(b, f.clone()))
118    }
119}
120
121impl<T: MappedEq> UnorderedMappedEq for IndexSet<T> {
122    type Item = T;
123
124    fn len(&self) -> usize {
125        self.len()
126    }
127}
128
129impl<T: MappedEq> MappedEq for IndexSet<T> {
130    type BlankId = T::BlankId;
131
132    fn mapped_eq<'a, 'b, F: Clone + Fn(&'a Self::BlankId) -> &'b Self::BlankId>(&'a self, other: &Self, f: F) -> bool
133    where
134        Self::BlankId: 'a + 'b,
135    {
136        self.unordered_mapped_eq(other, f)
137    }
138}
139
140impl<T: MappedEq> MappedEq for Indexed<T> {
141    type BlankId = T::BlankId;
142
143    fn mapped_eq<'a, 'b, F: Clone + Fn(&'a Self::BlankId) -> &'b Self::BlankId>(&'a self, other: &Self, f: F) -> bool
144    where
145        Self::BlankId: 'a + 'b,
146    {
147        self.index() == other.index() && self.inner().mapped_eq(other.inner(), f)
148    }
149}
150
151impl<T: PartialEq, B: PartialEq> MappedEq for Id<T, B> {
152    type BlankId = B;
153
154    fn mapped_eq<'a, 'b, F: Clone + Fn(&'a Self::BlankId) -> &'b Self::BlankId>(&'a self, other: &Self, f: F) -> bool
155    where
156        Self::BlankId: 'a + 'b,
157    {
158        match (self, other) {
159            (Self::Valid(a), Self::Valid(b)) => a.mapped_eq(b, f),
160            (Self::Invalid(a), Self::Invalid(b)) => a == b,
161            _ => false,
162        }
163    }
164}
165
166impl<T: PartialEq, B: PartialEq> MappedEq for ValidId<T, B> {
167    type BlankId = B;
168
169    fn mapped_eq<'a, 'b, F: Clone + Fn(&'a Self::BlankId) -> &'b Self::BlankId>(&'a self, other: &Self, f: F) -> bool
170    where
171        Self::BlankId: 'a + 'b,
172    {
173        match (self, other) {
174            (Self::Blank(a), Self::Blank(b)) => f(a) == b,
175            (Self::Iri(a), Self::Iri(b)) => a == b,
176            _ => false,
177        }
178    }
179}
180
181impl<T: Eq + Hash, B: Eq + Hash> MappedEq for super::Object<T, B> {
182    type BlankId = B;
183
184    fn mapped_eq<'a, 'b, F: Clone + Fn(&'a B) -> &'b B>(&'a self, other: &Self, f: F) -> bool
185    where
186        B: 'a + 'b,
187    {
188        match (self, other) {
189            (Self::Value(a), Self::Value(b)) => a == b,
190            (Self::Node(a), Self::Node(b)) => a.mapped_eq(b, f),
191            (Self::List(a), Self::List(b)) => a.mapped_eq(b, f),
192            _ => false,
193        }
194    }
195}
196
197fn opt_mapped_eq<'a, 'b, A: MappedEq, F: Clone + Fn(&'a A::BlankId) -> &'b A::BlankId>(a: Option<&'a A>, b: Option<&A>, f: F) -> bool
198where
199    A::BlankId: 'a + 'b,
200{
201    match (a, b) {
202        (Some(a), Some(b)) => a.mapped_eq(b, f),
203        (None, None) => true,
204        _ => false,
205    }
206}
207
208impl<T: Eq + Hash, B: Eq + Hash> MappedEq for super::Node<T, B> {
209    type BlankId = B;
210
211    fn mapped_eq<'a, 'b, F: Clone + Fn(&'a B) -> &'b B>(&'a self, other: &Self, f: F) -> bool
212    where
213        B: 'a + 'b,
214    {
215        opt_mapped_eq(self.id.as_ref(), other.id.as_ref(), f.clone())
216            && opt_mapped_eq(self.included_entry(), other.included_entry(), f.clone())
217            && opt_mapped_eq(self.graph_entry(), other.graph_entry(), f.clone())
218            && self.properties().mapped_eq(other.properties(), f.clone())
219            && opt_mapped_eq(self.reverse_properties_entry(), other.reverse_properties_entry(), f)
220    }
221}
222
223impl<T: Eq + Hash, B: Eq + Hash> MappedEq for super::node::Properties<T, B> {
224    type BlankId = B;
225
226    fn mapped_eq<'a, 'b, F: Clone + Fn(&'a B) -> &'b B>(&'a self, other: &Self, f: F) -> bool
227    where
228        B: 'a + 'b,
229    {
230        if self.len() == other.len() {
231            let other_vec: Vec<_> = other.iter().collect();
232            let mut selected = Vec::new();
233            selected.resize(other_vec.len(), false);
234
235            'self_items: for (prop, objects) in self {
236                for (i, sel) in selected.iter_mut().enumerate() {
237                    // SAFETY: `i < selected.len() == other_vec.len()`.
238                    let (other_prop, other_objects) = unsafe { other_vec.get(i).unwrap_unchecked() };
239                    if !*sel && prop.mapped_eq(other_prop, f.clone()) && objects.unordered_mapped_eq(other_objects, f.clone()) {
240                        *sel = true;
241                        continue 'self_items;
242                    }
243                }
244
245                return false;
246            }
247
248            true
249        } else {
250            false
251        }
252    }
253}
254
255impl<T: Eq + Hash, B: Eq + Hash> MappedEq for super::node::ReverseProperties<T, B> {
256    type BlankId = B;
257
258    fn mapped_eq<'a, 'b, F: Clone + Fn(&'a B) -> &'b B>(&'a self, other: &Self, f: F) -> bool
259    where
260        B: 'a + 'b,
261    {
262        if self.len() == other.len() {
263            let other_vec: Vec<_> = other.iter().collect();
264            let mut selected = Vec::new();
265            selected.resize(other_vec.len(), false);
266
267            'self_items: for (prop, nodes) in self {
268                for (i, sel) in selected.iter_mut().enumerate() {
269                    // SAFETY: `i < selected.len() == other_vec.len()`.
270                    let (other_prop, other_nodes) = unsafe { other_vec.get(i).unwrap_unchecked() };
271                    if !*sel && prop.mapped_eq(other_prop, f.clone()) && nodes.unordered_mapped_eq(other_nodes, f.clone()) {
272                        *sel = true;
273                        continue 'self_items;
274                    }
275                }
276
277                return false;
278            }
279
280            true
281        } else {
282            false
283        }
284    }
285}