1use crate::{Id, IndexSet, Indexed, ValidId};
2use std::hash::Hash;
3
4pub trait MappedEq<T: ?Sized = Self> {
6 type BlankId;
8 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 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 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 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}