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