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
18pub 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}