Skip to main content

linked_data_next/
predicate.rs

1use iref::{Iri, IriBuf};
2use rdf_types::{
3	BlankId, BlankIdBuf, Id, Interpretation, Vocabulary,
4	dataset::PatternMatchingDataset,
5	interpretation::{
6		ReverseBlankIdInterpretation, ReverseIdInterpretation, ReverseIriInterpretation,
7	},
8	vocabulary::{BlankIdVocabularyMut, IriVocabularyMut},
9};
10use std::collections::HashSet;
11use std::hash::Hash;
12
13use crate::{
14	Context, FromLinkedDataError, LinkedDataDeserializeSubject, LinkedDataResource,
15	LinkedDataSubject,
16};
17
18/// Type representing the objects of an RDF subject's predicate binding.
19pub trait LinkedDataPredicateObjects<I: Interpretation = (), V: Vocabulary = ()> {
20	fn visit_objects<S>(&self, visitor: S) -> Result<S::Ok, S::Error>
21	where
22		S: PredicateObjectsVisitor<I, V>;
23}
24
25impl<I: Interpretation, V: Vocabulary> LinkedDataPredicateObjects<I, V> for () {
26	fn visit_objects<S>(&self, visitor: S) -> Result<S::Ok, S::Error>
27	where
28		S: PredicateObjectsVisitor<I, V>,
29	{
30		visitor.end()
31	}
32}
33
34impl<I: Interpretation, V: Vocabulary, T: ?Sized + LinkedDataPredicateObjects<I, V>>
35	LinkedDataPredicateObjects<I, V> for &T
36{
37	fn visit_objects<S>(&self, visitor: S) -> Result<S::Ok, S::Error>
38	where
39		S: PredicateObjectsVisitor<I, V>,
40	{
41		T::visit_objects(self, visitor)
42	}
43}
44
45impl<I: Interpretation, V: Vocabulary, T: ?Sized + LinkedDataPredicateObjects<I, V>>
46	LinkedDataPredicateObjects<I, V> for Box<T>
47{
48	fn visit_objects<S>(&self, visitor: S) -> Result<S::Ok, S::Error>
49	where
50		S: PredicateObjectsVisitor<I, V>,
51	{
52		T::visit_objects(self, visitor)
53	}
54}
55
56impl<I: Interpretation, V: Vocabulary, T: LinkedDataSubject<I, V> + LinkedDataResource<I, V>>
57	LinkedDataPredicateObjects<I, V> for Option<T>
58{
59	fn visit_objects<S>(&self, mut visitor: S) -> Result<S::Ok, S::Error>
60	where
61		S: PredicateObjectsVisitor<I, V>,
62	{
63		if let Some(t) = self {
64			visitor.object(t)?;
65		}
66
67		visitor.end()
68	}
69}
70
71impl<I: Interpretation, V: Vocabulary, T: LinkedDataSubject<I, V> + LinkedDataResource<I, V>>
72	LinkedDataPredicateObjects<I, V> for [T]
73{
74	fn visit_objects<S>(&self, mut visitor: S) -> Result<S::Ok, S::Error>
75	where
76		S: PredicateObjectsVisitor<I, V>,
77	{
78		for t in self {
79			visitor.object(t)?;
80		}
81
82		visitor.end()
83	}
84}
85
86impl<I: Interpretation, V: Vocabulary, T: LinkedDataSubject<I, V> + LinkedDataResource<I, V>>
87	LinkedDataPredicateObjects<I, V> for Vec<T>
88{
89	fn visit_objects<S>(&self, mut visitor: S) -> Result<S::Ok, S::Error>
90	where
91		S: PredicateObjectsVisitor<I, V>,
92	{
93		for t in self {
94			visitor.object(t)?;
95		}
96
97		visitor.end()
98	}
99}
100
101impl<I: Interpretation, V: Vocabulary, T: LinkedDataSubject<I, V> + LinkedDataResource<I, V>>
102	LinkedDataPredicateObjects<I, V> for HashSet<T>
103{
104	fn visit_objects<S>(&self, mut visitor: S) -> Result<S::Ok, S::Error>
105	where
106		S: PredicateObjectsVisitor<I, V>,
107	{
108		for t in self.iter() {
109			visitor.object(t)?;
110		}
111
112		visitor.end()
113	}
114}
115
116impl<I: Interpretation, V: Vocabulary> LinkedDataPredicateObjects<I, V> for Iri
117where
118	V: IriVocabularyMut,
119{
120	fn visit_objects<S>(&self, mut visitor: S) -> Result<S::Ok, S::Error>
121	where
122		S: PredicateObjectsVisitor<I, V>,
123	{
124		visitor.object(self)?;
125		visitor.end()
126	}
127}
128
129impl<I: Interpretation, V: Vocabulary> LinkedDataPredicateObjects<I, V> for IriBuf
130where
131	V: IriVocabularyMut,
132{
133	fn visit_objects<S>(&self, mut visitor: S) -> Result<S::Ok, S::Error>
134	where
135		S: PredicateObjectsVisitor<I, V>,
136	{
137		visitor.object(self)?;
138		visitor.end()
139	}
140}
141
142impl<I: Interpretation, V: Vocabulary> LinkedDataPredicateObjects<I, V> for BlankId
143where
144	V: BlankIdVocabularyMut,
145{
146	fn visit_objects<S>(&self, mut visitor: S) -> Result<S::Ok, S::Error>
147	where
148		S: PredicateObjectsVisitor<I, V>,
149	{
150		visitor.object(self)?;
151		visitor.end()
152	}
153}
154
155impl<I: Interpretation, V: Vocabulary> LinkedDataPredicateObjects<I, V> for BlankIdBuf
156where
157	V: BlankIdVocabularyMut,
158{
159	fn visit_objects<S>(&self, mut visitor: S) -> Result<S::Ok, S::Error>
160	where
161		S: PredicateObjectsVisitor<I, V>,
162	{
163		visitor.object(self)?;
164		visitor.end()
165	}
166}
167
168impl<I: Interpretation, V: Vocabulary, T, B> LinkedDataPredicateObjects<I, V> for Id<T, B>
169where
170	T: LinkedDataPredicateObjects<I, V>,
171	B: LinkedDataPredicateObjects<I, V>,
172{
173	fn visit_objects<S>(&self, visitor: S) -> Result<S::Ok, S::Error>
174	where
175		S: PredicateObjectsVisitor<I, V>,
176	{
177		match self {
178			Self::Iri(i) => i.visit_objects(visitor),
179			Self::Blank(b) => b.visit_objects(visitor),
180		}
181	}
182}
183
184pub trait PredicateObjectsVisitor<I: Interpretation, V: Vocabulary> {
185	type Ok;
186	type Error;
187
188	fn object<T>(&mut self, value: &T) -> Result<(), Self::Error>
189	where
190		T: ?Sized + LinkedDataResource<I, V> + LinkedDataSubject<I, V>;
191
192	fn end(self) -> Result<Self::Ok, Self::Error>;
193}
194
195pub trait LinkedDataDeserializePredicateObjects<I: Interpretation = (), V: Vocabulary = ()>:
196	Sized
197{
198	fn deserialize_objects_in<'a, D>(
199		vocabulary: &V,
200		interpretation: &I,
201		dataset: &D,
202		graph: Option<&I::Resource>,
203		objects: impl IntoIterator<Item = &'a I::Resource>,
204		context: Context<I>,
205	) -> Result<Self, FromLinkedDataError>
206	where
207		I::Resource: 'a,
208		D: PatternMatchingDataset<Resource = I::Resource>;
209
210	fn deserialize_objects<'a, D>(
211		vocabulary: &V,
212		interpretation: &I,
213		dataset: &D,
214		graph: Option<&I::Resource>,
215		objects: impl IntoIterator<Item = &'a I::Resource>,
216	) -> Result<Self, FromLinkedDataError>
217	where
218		I::Resource: 'a,
219		D: PatternMatchingDataset<Resource = I::Resource>,
220	{
221		Self::deserialize_objects_in(
222			vocabulary,
223			interpretation,
224			dataset,
225			graph,
226			objects,
227			Context::default(),
228		)
229	}
230}
231
232macro_rules! deserialize_single_object {
233	() => {
234		fn deserialize_objects_in<'a, D>(
235			vocabulary: &V,
236			interpretation: &I,
237			dataset: &D,
238			graph: Option<&I::Resource>,
239			objects: impl IntoIterator<Item = &'a I::Resource>,
240			context: $crate::Context<I>,
241		) -> Result<Self, FromLinkedDataError>
242		where
243			I::Resource: 'a,
244			D: PatternMatchingDataset<Resource = I::Resource>,
245		{
246			use crate::LinkedDataDeserializeSubject;
247			let mut objects = objects.into_iter();
248			match objects.next() {
249				Some(object) => {
250					if objects.next().is_none() {
251						Self::deserialize_subject_in(
252							vocabulary,
253							interpretation,
254							dataset,
255							graph,
256							object,
257							context,
258						)
259					} else {
260						Err(FromLinkedDataError::TooManyValues(
261							context.into_iris(vocabulary, interpretation),
262						))
263					}
264				}
265				None => Err(FromLinkedDataError::MissingRequiredValue(
266					context.into_iris(vocabulary, interpretation),
267				)),
268			}
269		}
270	};
271}
272
273impl<I: Interpretation, V: Vocabulary> LinkedDataDeserializePredicateObjects<I, V> for IriBuf
274where
275	I: ReverseIriInterpretation<Iri = V::Iri>,
276{
277	deserialize_single_object!();
278}
279
280impl<I: Interpretation, V: Vocabulary> LinkedDataDeserializePredicateObjects<I, V> for BlankIdBuf
281where
282	I: ReverseIriInterpretation<Iri = V::Iri> + ReverseBlankIdInterpretation<BlankId = V::BlankId>,
283{
284	deserialize_single_object!();
285}
286
287impl<I: Interpretation, V: Vocabulary> LinkedDataDeserializePredicateObjects<I, V> for Id
288where
289	I: ReverseIdInterpretation<Iri = V::Iri, BlankId = V::BlankId>,
290{
291	deserialize_single_object!();
292}
293
294impl<I: Interpretation, V: Vocabulary, T: LinkedDataDeserializePredicateObjects<I, V>>
295	LinkedDataDeserializePredicateObjects<I, V> for Box<T>
296{
297	fn deserialize_objects_in<'a, D>(
298		vocabulary: &V,
299		interpretation: &I,
300		dataset: &D,
301		graph: Option<&I::Resource>,
302		objects: impl IntoIterator<Item = &'a I::Resource>,
303		context: Context<I>,
304	) -> Result<Self, FromLinkedDataError>
305	where
306		I::Resource: 'a,
307		D: PatternMatchingDataset<Resource = I::Resource>,
308	{
309		T::deserialize_objects_in(vocabulary, interpretation, dataset, graph, objects, context)
310			.map(Box::new)
311	}
312}
313
314impl<I: Interpretation, V: Vocabulary, T: LinkedDataDeserializeSubject<I, V>>
315	LinkedDataDeserializePredicateObjects<I, V> for Option<T>
316where
317	I: ReverseIriInterpretation<Iri = V::Iri>,
318{
319	fn deserialize_objects_in<'a, D>(
320		vocabulary: &V,
321		interpretation: &I,
322		dataset: &D,
323		graph: Option<&I::Resource>,
324		objects: impl IntoIterator<Item = &'a I::Resource>,
325		context: Context<I>,
326	) -> Result<Self, FromLinkedDataError>
327	where
328		I::Resource: 'a,
329		D: PatternMatchingDataset<Resource = I::Resource>,
330	{
331		let mut objects = objects.into_iter();
332		match objects.next() {
333			Some(object) => {
334				if objects.next().is_none() {
335					T::deserialize_subject_in(
336						vocabulary,
337						interpretation,
338						dataset,
339						graph,
340						object,
341						context,
342					)
343					.map(Some)
344				} else {
345					Err(FromLinkedDataError::TooManyValues(
346						context.into_iris(vocabulary, interpretation),
347					))
348				}
349			}
350			None => Ok(None),
351		}
352	}
353}
354
355impl<I: Interpretation, V: Vocabulary, T: LinkedDataDeserializeSubject<I, V>>
356	LinkedDataDeserializePredicateObjects<I, V> for Vec<T>
357where
358	I: ReverseIriInterpretation<Iri = V::Iri>,
359{
360	fn deserialize_objects_in<'a, D>(
361		vocabulary: &V,
362		interpretation: &I,
363		dataset: &D,
364		graph: Option<&I::Resource>,
365		objects: impl IntoIterator<Item = &'a I::Resource>,
366		context: Context<I>,
367	) -> Result<Self, FromLinkedDataError>
368	where
369		I::Resource: 'a,
370		D: PatternMatchingDataset<Resource = I::Resource>,
371	{
372		objects
373			.into_iter()
374			.map(|object| {
375				T::deserialize_subject_in(
376					vocabulary,
377					interpretation,
378					dataset,
379					graph,
380					object,
381					context,
382				)
383			})
384			.collect::<Result<Vec<_>, _>>()
385	}
386}
387
388impl<I: Interpretation, V: Vocabulary, T: LinkedDataDeserializeSubject<I, V>>
389	LinkedDataDeserializePredicateObjects<I, V> for HashSet<T>
390where
391	I: ReverseIriInterpretation<Iri = V::Iri>,
392	T: Clone + Hash + Eq,
393{
394	fn deserialize_objects_in<'a, D>(
395		vocabulary: &V,
396		interpretation: &I,
397		dataset: &D,
398		graph: Option<&I::Resource>,
399		objects: impl IntoIterator<Item = &'a I::Resource>,
400		context: Context<I>,
401	) -> Result<Self, FromLinkedDataError>
402	where
403		I::Resource: 'a,
404		D: PatternMatchingDataset<Resource = I::Resource>,
405	{
406		objects
407			.into_iter()
408			.map(|object| {
409				T::deserialize_subject_in(
410					vocabulary,
411					interpretation,
412					dataset,
413					graph,
414					object,
415					context,
416				)
417			})
418			.collect::<Result<HashSet<_>, _>>()
419	}
420}