json_ld_core/object/
mapped_eq.rs

1use crate::{Id, Indexed, ValidId};
2use indexmap::IndexSet;
3use std::hash::Hash;
4
5pub trait MappedEq<T: ?Sized = Self> {
6	type BlankId;
7	/// Structural equality with mapped blank identifiers.
8	///
9	/// Does not care for metadata.
10	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}