Skip to main content

ld_core/
quads.rs

1use educe::Educe;
2use iri_rs::IriBuf;
3use rdfx::generator::LocalGeneratorInterpretation;
4use rdfx::{
5	Id, Interpretation, InterpretationMut, IsGraph, IsObject, IsPredicate, IsSubject,
6	LocalGenerator, LocalTerm, Quad, Resource, Term,
7	interpretation::{
8		GenerativeInterpretation, LocalInterpretationMut, ReverseInterpretation,
9		ReverseLocalInterpretation,
10	},
11};
12
13use crate::{
14	CowRdfTerm, GraphVisitor, InterpretedQuad, LinkedData, LinkedDataGraph, LinkedDataResource,
15	LinkedDataSubject, OwnedRdfTerm, PredicateObjectsVisitor, RdfQuad, ResourceInterpretation,
16	SubjectVisitor, Visitor,
17};
18
19/// Serializes `value` into quads whose components are resources of
20/// `interpretation`.
21pub fn to_interpreted_quads<I>(
22	interpretation: &mut I,
23	value: &impl LinkedData<I>,
24) -> Result<Vec<InterpretedQuad<I>>, IntoQuadsError>
25where
26	I: Interpretation + InterpretationMut + LocalInterpretationMut + GenerativeInterpretation,
27	I::Resource: Clone + Resource,
28{
29	value.visit(QuadSerializer {
30		interpretation,
31		domain: &mut InterpretationDomain,
32		result: Vec::new(),
33	})
34}
35
36/// Serializes `value` as a single subject in `graph`, returning its
37/// resource and the quads describing it.
38pub fn to_interpreted_subject_quads<I>(
39	interpretation: &mut I,
40	graph: Option<&I::Resource>,
41	value: &(impl LinkedDataSubject<I> + LinkedDataResource<I>),
42) -> Result<(I::Resource, Vec<InterpretedQuad<I>>), IntoQuadsError>
43where
44	I: Interpretation + InterpretationMut + LocalInterpretationMut + GenerativeInterpretation,
45	I::Resource: Clone + Resource,
46{
47	let mut result = Vec::new();
48
49	let i = value.interpretation(interpretation);
50	let subject = InterpretationDomain.subject(interpretation, i)?;
51
52	value.visit_subject(QuadPropertiesSerializer {
53		interpretation,
54		domain: &mut InterpretationDomain,
55		graph,
56		subject: SubjectOrObject::Subject(&subject),
57		result: &mut result,
58	})?;
59
60	Ok((subject, result))
61}
62
63/// Serializes `value` as the content of `graph`, in the interpretation
64/// domain.
65pub fn to_interpreted_graph_quads<I>(
66	interpretation: &mut I,
67	value: &(impl LinkedDataGraph<I> + LinkedDataResource<I>),
68) -> Result<(I::Resource, Vec<InterpretedQuad<I>>), IntoQuadsError>
69where
70	I: Interpretation + InterpretationMut + LocalInterpretationMut + GenerativeInterpretation,
71	I::Resource: Clone + Resource,
72{
73	let mut result = Vec::new();
74
75	let i = value.interpretation(interpretation);
76	let graph = InterpretationDomain.graph(interpretation, i)?;
77
78	value.visit_graph(QuadGraphSerializer {
79		interpretation,
80		domain: &mut InterpretationDomain,
81		graph: Some(&graph),
82		result: &mut result,
83	})?;
84
85	Ok((graph, result))
86}
87
88/// Serializes `value` into lexical quads, using the given interpretation to
89/// resolve resources into IRIs, blank ids and literals.
90pub fn to_lexical_quads_with<I>(
91	interpretation: &mut I,
92	value: &impl LinkedData<I>,
93) -> Result<Vec<RdfQuad>, IntoQuadsError>
94where
95	I: Interpretation
96		+ InterpretationMut
97		+ ReverseInterpretation
98		+ ReverseLocalInterpretation
99		+ GenerativeInterpretation,
100{
101	let mut domain = LexicalDomain;
102
103	value.visit(QuadSerializer {
104		interpretation,
105		domain: &mut domain,
106		result: Vec::new(),
107	})
108}
109
110/// Serializes `value` as a single subject in `graph`, returning its
111/// identifier and the lexical quads describing it.
112pub fn to_lexical_subject_quads_with<I>(
113	interpretation: &mut I,
114	graph: Option<&Id>,
115	value: &(impl LinkedDataSubject<I> + LinkedDataResource<I>),
116) -> Result<(Id, Vec<RdfQuad>), IntoQuadsError>
117where
118	I: Interpretation
119		+ InterpretationMut
120		+ ReverseInterpretation
121		+ ReverseLocalInterpretation
122		+ GenerativeInterpretation,
123	I::Resource: Clone,
124{
125	let mut result = Vec::new();
126
127	let i = value.interpretation(interpretation);
128	let subject = LexicalDomain.subject(interpretation, i)?;
129
130	value.visit_subject(QuadPropertiesSerializer {
131		interpretation,
132		domain: &mut LexicalDomain,
133		graph,
134		subject: SubjectOrObject::Subject(&subject),
135		result: &mut result,
136	})?;
137
138	Ok((subject, result))
139}
140
141/// Serializes `value` into lexical quads, drawing blank node identifiers
142/// from `generator`.
143pub fn to_lexical_quads<G: LocalGenerator>(
144	generator: G,
145	value: &impl LinkedData<LocalGeneratorInterpretation<G>>,
146) -> Result<Vec<RdfQuad>, IntoQuadsError> {
147	let mut interpretation = LocalGeneratorInterpretation::new(generator);
148	to_lexical_quads_with(&mut interpretation, value)
149}
150
151/// Serializes `value` as a single subject in `graph`, drawing blank node
152/// identifiers from `generator`.
153pub fn to_lexical_subject_quads<G: LocalGenerator>(
154	generator: G,
155	graph: Option<&Id>,
156	value: &(
157	     impl LinkedDataSubject<LocalGeneratorInterpretation<G>>
158	     + LinkedDataResource<LocalGeneratorInterpretation<G>>
159	 ),
160) -> Result<(Id, Vec<RdfQuad>), IntoQuadsError> {
161	let mut interpretation = LocalGeneratorInterpretation::new(generator);
162	to_lexical_subject_quads_with(&mut interpretation, graph, value)
163}
164
165/// Serializes `value` into quads, using the given interpretation.
166///
167/// Alias of [`to_lexical_quads_with`].
168pub fn to_quads_with<I>(
169	interpretation: &mut I,
170	value: &impl LinkedData<I>,
171) -> Result<Vec<RdfQuad>, IntoQuadsError>
172where
173	I: Interpretation
174		+ InterpretationMut
175		+ ReverseInterpretation
176		+ ReverseLocalInterpretation
177		+ GenerativeInterpretation,
178{
179	to_lexical_quads_with(interpretation, value)
180}
181
182/// Serializes `value` into quads, drawing blank node identifiers from
183/// `generator`.
184///
185/// Alias of [`to_lexical_quads`].
186pub fn to_quads<G: LocalGenerator>(
187	generator: G,
188	value: &impl LinkedData<LocalGeneratorInterpretation<G>>,
189) -> Result<Vec<RdfQuad>, IntoQuadsError> {
190	to_lexical_quads(generator, value)
191}
192
193#[derive(Debug, thiserror::Error)]
194/// Error raised while serializing a value into quads.
195pub enum IntoQuadsError {
196	#[error("invalid graph label")]
197	/// A resource used as a graph label is neither an IRI nor a blank node.
198	Graph,
199
200	#[error("invalid subject")]
201	/// A resource used as a subject is neither an IRI nor a blank node.
202	Subject,
203
204	#[error("invalid predicate")]
205	/// A resource used as a predicate is not an IRI.
206	Predicate,
207
208	#[error("missing lexical representation")]
209	/// A resource has no lexical representation in the interpretation.
210	MissingLexicalRepresentation,
211}
212
213trait Domain<I: Interpretation> {
214	type Subject: Clone + IsSubject + IsGraph;
215	type Predicate: Clone + IsPredicate;
216	type Object: IsObject;
217	type ObjectRef<'a>: Copy
218	where
219		I::Resource: 'a,
220		Self: 'a;
221
222	fn subject(
223		&mut self,
224		interpretation: &mut I,
225		value: ResourceInterpretation<I>,
226	) -> Result<Self::Subject, IntoQuadsError>;
227
228	fn predicate(
229		&mut self,
230		interpretation: &mut I,
231		value: ResourceInterpretation<I>,
232	) -> Result<Self::Predicate, IntoQuadsError>;
233
234	fn object(
235		&mut self,
236		interpretation: &mut I,
237		value: ResourceInterpretation<I>,
238	) -> Result<Self::Object, IntoQuadsError>;
239
240	fn graph(
241		&mut self,
242		interpretation: &mut I,
243		value: ResourceInterpretation<I>,
244	) -> Result<Self::Subject, IntoQuadsError>;
245
246	fn object_as_subject(&self, object: &Self::Object) -> Result<Self::Subject, IntoQuadsError>;
247
248	fn subject_as_object<'a>(
249		&self,
250		subject: &'a Self::Subject,
251	) -> Result<Self::ObjectRef<'a>, IntoQuadsError>
252	where
253		I::Resource: 'a;
254
255	fn object_as_ref<'a>(object: &'a Self::Object) -> Self::ObjectRef<'a>
256	where
257		I::Resource: 'a;
258
259	fn cloned_object_ref<'a>(object_ref: Self::ObjectRef<'a>) -> Self::Object
260	where
261		I::Resource: 'a;
262}
263
264type DomainQuad<I, D> = Quad<
265	<D as Domain<I>>::Subject,
266	<D as Domain<I>>::Predicate,
267	<D as Domain<I>>::Object,
268	<D as Domain<I>>::Subject,
269>;
270
271struct InterpretationDomain;
272
273#[allow(clippy::type_complexity)]
274fn resource_to_local_term<I>(
275	interpretation: &I,
276	r: &I::Resource,
277) -> Result<LocalTerm, IntoQuadsError>
278where
279	I: ReverseInterpretation + ReverseLocalInterpretation,
280{
281	if let Some(iri) = interpretation.iris_of(r).next() {
282		return Ok(LocalTerm::iri(iri.into_owned()));
283	}
284
285	if let Some(lit) = interpretation.literals_of(r).next() {
286		return Ok(LocalTerm::literal(lit.into_owned()));
287	}
288
289	if let Some(blank_id) = interpretation.blank_ids_of(r).next() {
290		return Ok(LocalTerm::BlankId(blank_id.into_owned()));
291	}
292
293	Err(IntoQuadsError::MissingLexicalRepresentation)
294}
295
296fn resource_to_id<I>(interpretation: &I, r: &I::Resource) -> Result<Id, IntoQuadsError>
297where
298	I: ReverseInterpretation + ReverseLocalInterpretation,
299{
300	if let Some(iri) = interpretation.iris_of(r).next() {
301		return Ok(Id::Iri(iri.into_owned()));
302	}
303
304	if let Some(blank_id) = interpretation.blank_ids_of(r).next() {
305		return Ok(Id::BlankId(blank_id.into_owned()));
306	}
307
308	Err(IntoQuadsError::MissingLexicalRepresentation)
309}
310
311fn cow_term_into_id(t: CowRdfTerm<'_>) -> Option<Id> {
312	let owned = t.into_owned();
313	owned.into_id()
314}
315
316fn cow_term_into_iri(t: CowRdfTerm<'_>) -> Option<IriBuf> {
317	match t.into_owned() {
318		OwnedRdfTerm::Iri(i) => Some(i),
319		_ => None,
320	}
321}
322
323impl<I> Domain<I> for InterpretationDomain
324where
325	I: Interpretation + InterpretationMut + LocalInterpretationMut + GenerativeInterpretation,
326	I::Resource: Clone + Resource,
327{
328	type Subject = I::Resource;
329	type Predicate = I::Resource;
330	type Object = I::Resource;
331	type ObjectRef<'a>
332		= &'a I::Resource
333	where
334		I::Resource: 'a;
335
336	fn subject(
337		&mut self,
338		interpretation: &mut I,
339		value: ResourceInterpretation<I>,
340	) -> Result<Self::Subject, IntoQuadsError> {
341		match value {
342			ResourceInterpretation::Interpreted(r) => Ok(r.clone()),
343			ResourceInterpretation::Uninterpreted(u) => match u {
344				Some(t) => match t.into_owned() {
345					OwnedRdfTerm::Iri(i) => {
346						Ok(interpretation.insert_iri(std::borrow::Cow::Owned(i)))
347					}
348					OwnedRdfTerm::BlankId(b) => {
349						Ok(interpretation.insert_blank_id(std::borrow::Cow::Owned(b)))
350					}
351					OwnedRdfTerm::Literal(_) => Err(IntoQuadsError::Subject),
352				},
353				None => Ok(interpretation.new_resource()),
354			},
355		}
356	}
357
358	fn predicate(
359		&mut self,
360		interpretation: &mut I,
361		value: ResourceInterpretation<I>,
362	) -> Result<Self::Predicate, IntoQuadsError> {
363		match value {
364			ResourceInterpretation::Interpreted(r) => Ok(r.clone()),
365			ResourceInterpretation::Uninterpreted(u) => match u {
366				Some(t) => match t.into_owned() {
367					OwnedRdfTerm::Iri(i) => {
368						Ok(interpretation.insert_iri(std::borrow::Cow::Owned(i)))
369					}
370					_ => Err(IntoQuadsError::Predicate),
371				},
372				None => Err(IntoQuadsError::Predicate),
373			},
374		}
375	}
376
377	fn object(
378		&mut self,
379		interpretation: &mut I,
380		value: ResourceInterpretation<I>,
381	) -> Result<Self::Object, IntoQuadsError> {
382		match value {
383			ResourceInterpretation::Interpreted(r) => Ok(r.clone()),
384			ResourceInterpretation::Uninterpreted(u) => match u {
385				Some(t) => match t.into_owned() {
386					OwnedRdfTerm::Iri(i) => {
387						Ok(interpretation.insert_iri(std::borrow::Cow::Owned(i)))
388					}
389					OwnedRdfTerm::BlankId(b) => {
390						Ok(interpretation.insert_blank_id(std::borrow::Cow::Owned(b)))
391					}
392					OwnedRdfTerm::Literal(l) => Ok(l.embed_into(interpretation)),
393				},
394				None => Ok(interpretation.new_resource()),
395			},
396		}
397	}
398
399	fn graph(
400		&mut self,
401		interpretation: &mut I,
402		value: ResourceInterpretation<I>,
403	) -> Result<Self::Subject, IntoQuadsError> {
404		match value {
405			ResourceInterpretation::Interpreted(r) => Ok(r.clone()),
406			ResourceInterpretation::Uninterpreted(u) => match u {
407				Some(t) => match t.into_owned() {
408					OwnedRdfTerm::Iri(i) => {
409						Ok(interpretation.insert_iri(std::borrow::Cow::Owned(i)))
410					}
411					OwnedRdfTerm::BlankId(b) => {
412						Ok(interpretation.insert_blank_id(std::borrow::Cow::Owned(b)))
413					}
414					OwnedRdfTerm::Literal(_) => Err(IntoQuadsError::Graph),
415				},
416				None => Ok(interpretation.new_resource()),
417			},
418		}
419	}
420
421	fn object_as_subject(&self, object: &Self::Object) -> Result<Self::Subject, IntoQuadsError> {
422		Ok(object.clone())
423	}
424
425	fn subject_as_object<'a>(
426		&self,
427		subject: &'a Self::Subject,
428	) -> Result<Self::ObjectRef<'a>, IntoQuadsError>
429	where
430		I::Resource: 'a,
431	{
432		Ok(subject)
433	}
434
435	fn object_as_ref<'a>(object: &'a Self::Object) -> Self::ObjectRef<'a>
436	where
437		I::Resource: 'a,
438	{
439		object
440	}
441
442	fn cloned_object_ref<'a>(object_ref: Self::ObjectRef<'a>) -> Self::Object
443	where
444		I::Resource: 'a,
445	{
446		object_ref.clone()
447	}
448}
449
450struct LexicalDomain;
451
452fn lexical_term_into_local(t: CowRdfTerm<'_>) -> LocalTerm {
453	match t.into_owned() {
454		OwnedRdfTerm::Iri(i) => LocalTerm::iri(i),
455		OwnedRdfTerm::BlankId(b) => LocalTerm::BlankId(b),
456		OwnedRdfTerm::Literal(l) => LocalTerm::literal(l.into_lexical()),
457	}
458}
459
460impl<I> Domain<I> for LexicalDomain
461where
462	I: Interpretation
463		+ InterpretationMut
464		+ ReverseInterpretation
465		+ ReverseLocalInterpretation
466		+ GenerativeInterpretation,
467{
468	type Subject = Id;
469	type Predicate = IriBuf;
470	type Object = LocalTerm;
471	type ObjectRef<'a>
472		= LocalTermRefCopy<'a>
473	where
474		I::Resource: 'a;
475
476	fn subject(
477		&mut self,
478		interpretation: &mut I,
479		value: ResourceInterpretation<I>,
480	) -> Result<Self::Subject, IntoQuadsError> {
481		match value {
482			ResourceInterpretation::Interpreted(r) => resource_to_id(interpretation, r),
483			ResourceInterpretation::Uninterpreted(u) => match u {
484				Some(t) => cow_term_into_id(t).ok_or(IntoQuadsError::Subject),
485				None => {
486					let r = interpretation.new_resource();
487					resource_to_id(interpretation, &r)
488				}
489			},
490		}
491	}
492
493	fn predicate(
494		&mut self,
495		interpretation: &mut I,
496		value: ResourceInterpretation<I>,
497	) -> Result<Self::Predicate, IntoQuadsError> {
498		match value {
499			ResourceInterpretation::Interpreted(r) => match interpretation.iris_of(r).next() {
500				Some(iri) => Ok(iri.into_owned()),
501				None => Err(IntoQuadsError::Predicate),
502			},
503			ResourceInterpretation::Uninterpreted(u) => match u {
504				Some(t) => cow_term_into_iri(t).ok_or(IntoQuadsError::Predicate),
505				None => Err(IntoQuadsError::Predicate),
506			},
507		}
508	}
509
510	fn object(
511		&mut self,
512		interpretation: &mut I,
513		value: ResourceInterpretation<I>,
514	) -> Result<Self::Object, IntoQuadsError> {
515		match value {
516			ResourceInterpretation::Interpreted(r) => resource_to_local_term(interpretation, r),
517			ResourceInterpretation::Uninterpreted(u) => match u {
518				Some(t) => Ok(lexical_term_into_local(t)),
519				None => {
520					let r = interpretation.new_resource();
521					resource_to_local_term(interpretation, &r)
522				}
523			},
524		}
525	}
526
527	fn graph(
528		&mut self,
529		interpretation: &mut I,
530		value: ResourceInterpretation<I>,
531	) -> Result<Self::Subject, IntoQuadsError> {
532		match value {
533			ResourceInterpretation::Interpreted(r) => resource_to_id(interpretation, r),
534			ResourceInterpretation::Uninterpreted(u) => match u {
535				Some(t) => cow_term_into_id(t).ok_or(IntoQuadsError::Graph),
536				None => {
537					let r = interpretation.new_resource();
538					resource_to_id(interpretation, &r)
539				}
540			},
541		}
542	}
543
544	fn object_as_subject(&self, object: &Self::Object) -> Result<Self::Subject, IntoQuadsError> {
545		match object {
546			LocalTerm::BlankId(b) => Ok(Id::BlankId(b.clone())),
547			LocalTerm::Named(Term::Iri(i)) => Ok(Id::Iri(i.clone())),
548			_ => Err(IntoQuadsError::Subject),
549		}
550	}
551
552	fn subject_as_object<'a>(
553		&self,
554		subject: &'a Self::Subject,
555	) -> Result<Self::ObjectRef<'a>, IntoQuadsError>
556	where
557		I::Resource: 'a,
558	{
559		Ok(LocalTermRefCopy::Id(subject))
560	}
561
562	fn object_as_ref<'a>(object: &'a Self::Object) -> Self::ObjectRef<'a>
563	where
564		I::Resource: 'a,
565	{
566		LocalTermRefCopy::Term(object)
567	}
568
569	fn cloned_object_ref<'a>(object_ref: Self::ObjectRef<'a>) -> Self::Object
570	where
571		I::Resource: 'a,
572	{
573		match object_ref {
574			LocalTermRefCopy::Id(id) => match id {
575				Id::Iri(i) => LocalTerm::iri(i.clone()),
576				Id::BlankId(b) => LocalTerm::BlankId(b.clone()),
577			},
578			LocalTermRefCopy::Term(t) => t.clone(),
579		}
580	}
581}
582
583#[derive(Clone, Copy)]
584enum LocalTermRefCopy<'a> {
585	Id(&'a Id),
586	Term(&'a LocalTerm),
587}
588
589/// A simple serializer generating a list of `Quad`s.
590struct QuadSerializer<'a, I: Interpretation, D: Domain<I>> {
591	interpretation: &'a mut I,
592	domain: &'a mut D,
593	result: Vec<DomainQuad<I, D>>,
594}
595
596impl<'a, I: Interpretation, D: Domain<I>> Visitor<I> for QuadSerializer<'a, I, D> {
597	type Ok = Vec<DomainQuad<I, D>>;
598	type Error = IntoQuadsError;
599
600	fn default_graph<T>(&mut self, value: &T) -> Result<(), Self::Error>
601	where
602		T: ?Sized + crate::LinkedDataGraph<I>,
603	{
604		let graph_serializer = QuadGraphSerializer {
605			interpretation: self.interpretation,
606			domain: self.domain,
607			result: &mut self.result,
608			graph: None,
609		};
610
611		value.visit_graph(graph_serializer)
612	}
613
614	fn named_graph<T>(&mut self, value: &T) -> Result<(), Self::Error>
615	where
616		T: ?Sized + LinkedDataResource<I> + crate::LinkedDataGraph<I>,
617	{
618		let i = value.interpretation(self.interpretation);
619		let graph = self.domain.graph(self.interpretation, i)?;
620
621		let graph_serializer = QuadGraphSerializer {
622			interpretation: self.interpretation,
623			domain: self.domain,
624			result: &mut self.result,
625			graph: Some(&graph),
626		};
627
628		value.visit_graph(graph_serializer)
629	}
630
631	fn end(self) -> Result<Self::Ok, Self::Error> {
632		Ok(self.result)
633	}
634}
635
636struct QuadGraphSerializer<'a, I: Interpretation, D: Domain<I>> {
637	interpretation: &'a mut I,
638	domain: &'a mut D,
639	result: &'a mut Vec<DomainQuad<I, D>>,
640	graph: Option<&'a D::Subject>,
641}
642
643impl<'a, I: Interpretation, D: Domain<I>> GraphVisitor<I> for QuadGraphSerializer<'a, I, D> {
644	type Ok = ();
645	type Error = IntoQuadsError;
646
647	fn subject<T>(&mut self, value: &T) -> Result<(), Self::Error>
648	where
649		T: ?Sized + LinkedDataResource<I> + crate::LinkedDataSubject<I>,
650	{
651		let i = value.interpretation(self.interpretation);
652		let term = self.domain.subject(self.interpretation, i)?;
653
654		let properties_serializer = QuadPropertiesSerializer {
655			interpretation: self.interpretation,
656			domain: self.domain,
657			result: self.result,
658			graph: self.graph,
659			subject: SubjectOrObject::Subject(&term),
660		};
661
662		value.visit_subject(properties_serializer)
663	}
664
665	fn end(self) -> Result<Self::Ok, Self::Error> {
666		Ok(())
667	}
668}
669
670struct QuadPropertiesSerializer<'a, I: Interpretation, D: Domain<I>> {
671	interpretation: &'a mut I,
672	domain: &'a mut D,
673	result: &'a mut Vec<DomainQuad<I, D>>,
674	graph: Option<&'a D::Subject>,
675	subject: SubjectOrObject<'a, I, D>,
676}
677
678#[derive(Educe)]
679#[educe(Clone, Copy)]
680enum SubjectOrObject<'a, I: Interpretation, D: Domain<I>> {
681	Subject(&'a D::Subject),
682	Object(&'a D::Object),
683}
684
685impl<'a, I: Interpretation, D: Domain<I>> SubjectOrObject<'a, I, D> {
686	fn into_subject(self, domain: &D) -> Result<std::borrow::Cow<'a, D::Subject>, IntoQuadsError>
687	where
688		D::Subject: Clone,
689	{
690		match self {
691			Self::Subject(s) => Ok(std::borrow::Cow::Borrowed(s)),
692			Self::Object(o) => domain.object_as_subject(o).map(std::borrow::Cow::Owned),
693		}
694	}
695
696	fn into_object(self, domain: &D) -> Result<D::ObjectRef<'a>, IntoQuadsError> {
697		match self {
698			Self::Subject(s) => domain.subject_as_object(s),
699			Self::Object(o) => Ok(D::object_as_ref(o)),
700		}
701	}
702}
703
704impl<'a, I: Interpretation, D: Domain<I>> SubjectVisitor<I> for QuadPropertiesSerializer<'a, I, D> {
705	type Ok = ();
706	type Error = IntoQuadsError;
707
708	fn predicate<L, T>(&mut self, predicate: &L, value: &T) -> Result<(), Self::Error>
709	where
710		L: ?Sized + LinkedDataResource<I>,
711		T: ?Sized + crate::LinkedDataPredicateObjects<I>,
712	{
713		let subject = self.subject.into_subject(self.domain)?;
714
715		let i = predicate.interpretation(self.interpretation);
716		let term = self.domain.predicate(self.interpretation, i)?;
717
718		let objects_serializer = ObjectsSerializer {
719			interpretation: self.interpretation,
720			domain: self.domain,
721			result: self.result,
722			graph: self.graph,
723			subject: subject.as_ref(),
724			predicate: term,
725		};
726
727		value.visit_objects(objects_serializer)
728	}
729
730	fn reverse_predicate<L, T>(&mut self, predicate: &L, subjects: &T) -> Result<(), Self::Error>
731	where
732		L: ?Sized + LinkedDataResource<I>,
733		T: ?Sized + crate::LinkedDataPredicateObjects<I>,
734	{
735		let object = self.subject.into_object(self.domain)?;
736
737		let i = predicate.interpretation(self.interpretation);
738		let term = self.domain.predicate(self.interpretation, i)?;
739
740		let subjects_serializer = ReversePredicateSerializer {
741			interpretation: self.interpretation,
742			domain: self.domain,
743			result: self.result,
744			graph: self.graph,
745			object,
746			predicate: term,
747		};
748
749		subjects.visit_objects(subjects_serializer)
750	}
751
752	fn graph<T>(&mut self, value: &T) -> Result<(), Self::Error>
753	where
754		T: ?Sized + LinkedDataGraph<I>,
755	{
756		let graph = self.subject.into_subject(self.domain)?;
757
758		let graph_serializer = QuadGraphSerializer {
759			interpretation: self.interpretation,
760			domain: self.domain,
761			result: self.result,
762			graph: Some(graph.as_ref()),
763		};
764
765		value.visit_graph(graph_serializer)
766	}
767
768	fn include<T>(&mut self, value: &T) -> Result<(), Self::Error>
769	where
770		T: ?Sized + LinkedDataResource<I> + LinkedDataSubject<I>,
771	{
772		let i = value.interpretation(self.interpretation);
773		let subject = self.domain.subject(self.interpretation, i)?;
774
775		value.visit_subject(QuadPropertiesSerializer {
776			interpretation: self.interpretation,
777			domain: self.domain,
778			graph: self.graph,
779			subject: SubjectOrObject::Subject(&subject),
780			result: self.result,
781		})?;
782
783		Ok(())
784	}
785
786	fn end(self) -> Result<Self::Ok, Self::Error> {
787		Ok(())
788	}
789}
790
791struct ObjectsSerializer<'a, I: Interpretation, D: Domain<I>> {
792	interpretation: &'a mut I,
793	domain: &'a mut D,
794	result: &'a mut Vec<DomainQuad<I, D>>,
795	graph: Option<&'a D::Subject>,
796	subject: &'a D::Subject,
797	predicate: D::Predicate,
798}
799
800impl<'a, I: Interpretation, D: Domain<I>> PredicateObjectsVisitor<I>
801	for ObjectsSerializer<'a, I, D>
802{
803	type Ok = ();
804	type Error = IntoQuadsError;
805
806	fn object<T>(&mut self, value: &T) -> Result<(), Self::Error>
807	where
808		T: ?Sized + LinkedDataResource<I> + crate::LinkedDataSubject<I>,
809	{
810		let i = value.interpretation(self.interpretation);
811		let term = self.domain.object(self.interpretation, i)?;
812		let subject_serializer = QuadPropertiesSerializer {
813			interpretation: self.interpretation,
814			domain: self.domain,
815			result: self.result,
816			graph: self.graph,
817			subject: SubjectOrObject::Object(&term),
818		};
819
820		value.visit_subject(subject_serializer)?;
821		self.result.push(Quad(
822			self.subject.clone(),
823			self.predicate.clone(),
824			term,
825			self.graph.cloned(),
826		));
827		Ok(())
828	}
829
830	fn end(self) -> Result<Self::Ok, Self::Error> {
831		Ok(())
832	}
833}
834
835struct ReversePredicateSerializer<'a, I: Interpretation, D: Domain<I>> {
836	interpretation: &'a mut I,
837	domain: &'a mut D,
838	result: &'a mut Vec<DomainQuad<I, D>>,
839	graph: Option<&'a D::Subject>,
840	object: D::ObjectRef<'a>,
841	predicate: D::Predicate,
842}
843
844impl<'a, I: Interpretation, D: Domain<I>> PredicateObjectsVisitor<I>
845	for ReversePredicateSerializer<'a, I, D>
846{
847	type Ok = ();
848	type Error = IntoQuadsError;
849
850	fn object<T>(&mut self, value: &T) -> Result<(), Self::Error>
851	where
852		T: ?Sized + LinkedDataResource<I> + crate::LinkedDataSubject<I>,
853	{
854		let i = value.interpretation(self.interpretation);
855		let subject = self.domain.subject(self.interpretation, i)?;
856
857		let subject_serializer = QuadPropertiesSerializer {
858			interpretation: self.interpretation,
859			domain: self.domain,
860			result: self.result,
861			graph: self.graph,
862			subject: SubjectOrObject::Subject(&subject),
863		};
864
865		value.visit_subject(subject_serializer)?;
866		self.result.push(Quad(
867			subject,
868			self.predicate.clone(),
869			D::cloned_object_ref(self.object),
870			self.graph.cloned(),
871		));
872		Ok(())
873	}
874
875	fn end(self) -> Result<Self::Ok, Self::Error> {
876		Ok(())
877	}
878}