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