rdf_types/
quad.rs

1use std::{cmp::Ordering, fmt};
2
3use iref::{Iri, IriBuf};
4
5use crate::{
6	interpretation::Interpret,
7	vocabulary::{
8		ByRef, EmbedIntoVocabulary, EmbeddedIntoVocabulary, ExtractFromVocabulary,
9		ExtractedFromVocabulary, TryExtractFromVocabulary,
10	},
11	GraphLabel, Id, Interpretation, LexicalGraphLabelRef, LexicalObjectRef, LexicalSubjectRef,
12	Object, RdfDisplay, Term, Triple,
13};
14
15#[cfg(feature = "contextual")]
16use contextual::{DisplayWithContext, WithContext};
17
18#[cfg(feature = "contextual")]
19use crate::RdfDisplayWithContext;
20
21/// Lexical RDF quad.
22pub type LexicalQuad = Quad<Id, IriBuf, Object, GraphLabel>;
23
24/// Lexical RDF quad reference.
25pub type LexicalQuadRef<'a> =
26	Quad<LexicalSubjectRef<'a>, &'a Iri, LexicalObjectRef<'a>, LexicalGraphLabelRef<'a>>;
27
28/// RDF quad.
29#[derive(Clone, Copy, Eq, Ord, Hash, Debug)]
30#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
31pub struct Quad<S = Term, P = S, O = S, G = S>(pub S, pub P, pub O, pub Option<G>);
32
33impl<S, P, O, G> Quad<S, P, O, G> {
34	#[deprecated(since = "0.18.4", note = "please use `as_ref` instead")]
35	pub fn borrow_components(&self) -> Quad<&S, &P, &O, &G> {
36		self.as_ref()
37	}
38
39	/// Borrows each component of the quad.
40	pub fn as_ref(&self) -> Quad<&S, &P, &O, &G> {
41		Quad(&self.0, &self.1, &self.2, self.3.as_ref())
42	}
43}
44
45impl<S, P, O, G> Quad<&S, &P, &O, &G> {
46	pub fn cloned(&self) -> Quad<S, P, O, G>
47	where
48		S: Clone,
49		P: Clone,
50		O: Clone,
51		G: Clone,
52	{
53		Quad(
54			self.0.clone(),
55			self.1.clone(),
56			self.2.clone(),
57			self.3.cloned(),
58		)
59	}
60
61	pub fn into_cloned(self) -> Quad<S, P, O, G>
62	where
63		S: Clone,
64		P: Clone,
65		O: Clone,
66		G: Clone,
67	{
68		Quad(
69			self.0.clone(),
70			self.1.clone(),
71			self.2.clone(),
72			self.3.cloned(),
73		)
74	}
75}
76
77impl<S, P, O, G> Quad<&S, &P, &O, &G> {
78	pub fn copied(&self) -> Quad<S, P, O, G>
79	where
80		S: Copy,
81		P: Copy,
82		O: Copy,
83		G: Copy,
84	{
85		Quad(*self.0, *self.1, *self.2, self.3.copied())
86	}
87
88	pub fn into_copied(self) -> Quad<S, P, O, G>
89	where
90		S: Copy,
91		P: Copy,
92		O: Copy,
93		G: Copy,
94	{
95		Quad(*self.0, *self.1, *self.2, self.3.copied())
96	}
97}
98
99impl LexicalQuad {
100	pub fn as_lexical_quad_ref(&self) -> LexicalQuadRef {
101		Quad(
102			self.0.as_lexical_subject_ref(),
103			self.1.as_iri(),
104			self.2.as_lexical_object_ref(),
105			self.3.as_ref().map(GraphLabel::as_graph_label_ref),
106		)
107	}
108}
109
110impl LexicalQuadRef<'_> {
111	pub fn into_owned(self) -> LexicalQuad {
112		Quad(
113			self.0.into_owned(),
114			self.1.to_owned(),
115			self.2.into_owned(),
116			self.3.map(LexicalGraphLabelRef::into_owned),
117		)
118	}
119}
120
121impl<
122		V,
123		S: EmbedIntoVocabulary<V>,
124		P: EmbedIntoVocabulary<V>,
125		O: EmbedIntoVocabulary<V>,
126		G: EmbedIntoVocabulary<V>,
127	> EmbedIntoVocabulary<V> for Quad<S, P, O, G>
128{
129	type Embedded = Quad<S::Embedded, P::Embedded, O::Embedded, G::Embedded>;
130
131	fn embed_into_vocabulary(self, vocabulary: &mut V) -> Self::Embedded {
132		Quad(
133			self.0.embed_into_vocabulary(vocabulary),
134			self.1.embed_into_vocabulary(vocabulary),
135			self.2.embed_into_vocabulary(vocabulary),
136			self.3.embed_into_vocabulary(vocabulary),
137		)
138	}
139}
140
141impl<
142		V,
143		S: EmbeddedIntoVocabulary<V>,
144		P: EmbeddedIntoVocabulary<V>,
145		O: EmbeddedIntoVocabulary<V>,
146		G: EmbeddedIntoVocabulary<V>,
147	> EmbeddedIntoVocabulary<V> for Quad<S, P, O, G>
148{
149	type Embedded = Quad<S::Embedded, P::Embedded, O::Embedded, G::Embedded>;
150
151	fn embedded_into_vocabulary(&self, vocabulary: &mut V) -> Self::Embedded {
152		Quad(
153			self.0.embedded_into_vocabulary(vocabulary),
154			self.1.embedded_into_vocabulary(vocabulary),
155			self.2.embedded_into_vocabulary(vocabulary),
156			self.3.embedded_into_vocabulary(vocabulary),
157		)
158	}
159}
160
161impl<S, P, O, G> Quad<S, P, O, G> {
162	/// Creates a new quad.
163	pub fn new(subject: S, predicate: P, object: O, graph: Option<G>) -> Self {
164		Self(subject, predicate, object, graph)
165	}
166
167	/// Returns a reference to the subject of the quad,
168	/// the first component.
169	pub fn subject(&self) -> &S {
170		&self.0
171	}
172
173	/// Returns a mutable reference to the subject of the quad,
174	/// the first component.
175	pub fn subject_mut(&mut self) -> &mut S {
176		&mut self.0
177	}
178
179	/// Turns the quad into its subject,
180	/// the first component.
181	pub fn into_subject(self) -> S {
182		self.0
183	}
184
185	/// Returns a reference to the predicate of the quad,
186	/// the second component.
187	pub fn predicate(&self) -> &P {
188		&self.1
189	}
190
191	/// Returns a mutable reference to the predicate of the quad,
192	/// the second component.
193	pub fn predicate_mut(&mut self) -> &mut P {
194		&mut self.1
195	}
196
197	/// Turns the quad into its predicate,
198	/// the second component.
199	pub fn into_predicate(self) -> P {
200		self.1
201	}
202
203	/// Returns a reference to the object of the quad,
204	/// the third component.
205	pub fn object(&self) -> &O {
206		&self.2
207	}
208
209	/// Returns a mutable reference to the object of the quad,
210	/// the third component.
211	pub fn object_mut(&mut self) -> &mut O {
212		&mut self.2
213	}
214
215	/// Turns the quad into its object,
216	/// the third component.
217	pub fn into_object(self) -> O {
218		self.2
219	}
220
221	/// Returns a reference to the graph of the quad,
222	/// the fourth component.
223	pub fn graph(&self) -> Option<&G> {
224		self.3.as_ref()
225	}
226
227	/// Returns a mutable reference to the graph of the quad,
228	/// the fourth component.
229	pub fn graph_mut(&mut self) -> Option<&mut G> {
230		self.3.as_mut()
231	}
232
233	/// Turns the quad into its graph,
234	/// the fourth component.
235	pub fn into_graph(self) -> Option<G> {
236		self.3
237	}
238
239	pub fn into_parts(self) -> (S, P, O, Option<G>) {
240		(self.0, self.1, self.2, self.3)
241	}
242
243	/// Turns this quad into a triple and its graph component.
244	pub fn into_triple(self) -> (Triple<S, P, O>, Option<G>) {
245		(Triple(self.0, self.1, self.2), self.3)
246	}
247
248	/// Maps the subject with the given function.
249	pub fn map_subject<U>(self, f: impl FnOnce(S) -> U) -> Quad<U, P, O, G> {
250		Quad(f(self.0), self.1, self.2, self.3)
251	}
252
253	/// Maps the subject with the given function.
254	pub fn map_predicate<U>(self, f: impl FnOnce(P) -> U) -> Quad<S, U, O, G> {
255		Quad(self.0, f(self.1), self.2, self.3)
256	}
257
258	/// Maps the subject with the given function.
259	pub fn map_object<U>(self, f: impl FnOnce(O) -> U) -> Quad<S, P, U, G> {
260		Quad(self.0, self.1, f(self.2), self.3)
261	}
262
263	/// Maps the graph with the given function.
264	pub fn map_graph<U>(self, f: impl FnOnce(Option<G>) -> Option<U>) -> Quad<S, P, O, U> {
265		Quad(self.0, self.1, self.2, f(self.3))
266	}
267
268	/// Maps every quad component with the given functions, one for each
269	/// component.
270	pub fn map_all<S2, P2, O2, G2>(
271		self,
272		s: impl FnOnce(S) -> S2,
273		p: impl FnOnce(P) -> P2,
274		o: impl FnOnce(O) -> O2,
275		g: impl FnOnce(Option<G>) -> Option<G2>,
276	) -> Quad<S2, P2, O2, G2> {
277		Quad(s(self.0), p(self.1), o(self.2), g(self.3))
278	}
279}
280
281impl<T> Quad<T, T, T, T> {
282	/// Maps the components with the given function.
283	pub fn map<U>(self, mut f: impl FnMut(T) -> U) -> Quad<U, U, U, U> {
284		Quad(f(self.0), f(self.1), f(self.2), self.3.map(f))
285	}
286}
287
288impl<S: Interpret<I>, P: Interpret<I>, O: Interpret<I>, G: Interpret<I>, I: Interpretation>
289	Interpret<I> for Quad<S, P, O, G>
290{
291	type Interpreted = Quad<S::Interpreted, P::Interpreted, O::Interpreted, G::Interpreted>;
292
293	fn interpret(self, interpretation: &mut I) -> Self::Interpreted {
294		Quad(
295			self.0.interpret(interpretation),
296			self.1.interpret(interpretation),
297			self.2.interpret(interpretation),
298			self.3.interpret(interpretation),
299		)
300	}
301}
302
303impl<
304		V,
305		S: ExtractFromVocabulary<V>,
306		P: ExtractFromVocabulary<V>,
307		O: ExtractFromVocabulary<V>,
308		G: ExtractFromVocabulary<V>,
309	> ExtractFromVocabulary<V> for Quad<S, P, O, G>
310{
311	type Extracted = Quad<S::Extracted, P::Extracted, O::Extracted, G::Extracted>;
312
313	fn extract_from_vocabulary(self, vocabulary: &V) -> Self::Extracted {
314		Quad(
315			self.0.extract_from_vocabulary(vocabulary),
316			self.1.extract_from_vocabulary(vocabulary),
317			self.2.extract_from_vocabulary(vocabulary),
318			self.3.extract_from_vocabulary(vocabulary),
319		)
320	}
321}
322
323impl<V, S, P, O, G> ExtractFromVocabulary<V> for ByRef<Quad<S, P, O, G>>
324where
325	ByRef<S>: ExtractFromVocabulary<V>,
326	ByRef<P>: ExtractFromVocabulary<V>,
327	ByRef<O>: ExtractFromVocabulary<V>,
328	ByRef<G>: ExtractFromVocabulary<V>,
329{
330	type Extracted = Quad<
331		<ByRef<S> as ExtractFromVocabulary<V>>::Extracted,
332		<ByRef<P> as ExtractFromVocabulary<V>>::Extracted,
333		<ByRef<O> as ExtractFromVocabulary<V>>::Extracted,
334		<ByRef<G> as ExtractFromVocabulary<V>>::Extracted,
335	>;
336
337	fn extract_from_vocabulary(self, vocabulary: &V) -> Self::Extracted {
338		Quad(
339			ByRef(self.0 .0).extract_from_vocabulary(vocabulary),
340			ByRef(self.0 .1).extract_from_vocabulary(vocabulary),
341			ByRef(self.0 .2).extract_from_vocabulary(vocabulary),
342			ByRef(self.0 .3).extract_from_vocabulary(vocabulary),
343		)
344	}
345}
346
347impl<
348		V,
349		S: ExtractedFromVocabulary<V>,
350		P: ExtractedFromVocabulary<V>,
351		O: ExtractedFromVocabulary<V>,
352		G: ExtractedFromVocabulary<V>,
353	> ExtractedFromVocabulary<V> for Quad<S, P, O, G>
354{
355	type Extracted = Quad<S::Extracted, P::Extracted, O::Extracted, G::Extracted>;
356
357	fn extracted_from_vocabulary(&self, vocabulary: &V) -> Self::Extracted {
358		Quad(
359			self.0.extracted_from_vocabulary(vocabulary),
360			self.1.extracted_from_vocabulary(vocabulary),
361			self.2.extracted_from_vocabulary(vocabulary),
362			self.3.extracted_from_vocabulary(vocabulary),
363		)
364	}
365}
366
367/// Type that can turn a `Quad<S, P, O, G>` into a `Quad`.
368pub trait TryExportQuad<S, P, O, G> {
369	type Error;
370
371	fn try_export_quad(&self, quad: Quad<S, P, O, G>) -> Result<LexicalQuad, Self::Error>;
372}
373
374/// Error returned when calling [`try_extract_from_vocabulary`][1] on a
375/// [`Quad`].
376///
377/// [1]: TryExtractFromVocabulary::try_extract_from_vocabulary
378#[derive(Debug, thiserror::Error)]
379pub enum QuadExportFailed<S, P, O, G> {
380	#[error("invalid subject: {0}")]
381	Subject(S),
382
383	#[error("invalid predicate: {0}")]
384	Predicate(P),
385
386	#[error("invalid object: {0}")]
387	Object(O),
388
389	#[error("invalid graph label: {0}")]
390	Graph(G),
391}
392
393impl<
394		V,
395		S: TryExtractFromVocabulary<V>,
396		P: TryExtractFromVocabulary<V>,
397		O: TryExtractFromVocabulary<V>,
398		G: TryExtractFromVocabulary<V>,
399	> TryExtractFromVocabulary<V> for Quad<S, P, O, G>
400{
401	type Extracted = Quad<S::Extracted, P::Extracted, O::Extracted, G::Extracted>;
402	type Error = QuadExportFailed<S::Error, P::Error, O::Error, G::Error>;
403
404	fn try_extract_from_vocabulary(self, vocabulary: &V) -> Result<Self::Extracted, Self::Error> {
405		Ok(Quad(
406			self.0
407				.try_extract_from_vocabulary(vocabulary)
408				.map_err(QuadExportFailed::Subject)?,
409			self.1
410				.try_extract_from_vocabulary(vocabulary)
411				.map_err(QuadExportFailed::Predicate)?,
412			self.2
413				.try_extract_from_vocabulary(vocabulary)
414				.map_err(QuadExportFailed::Object)?,
415			self.3
416				.try_extract_from_vocabulary(vocabulary)
417				.map_err(QuadExportFailed::Graph)?,
418		))
419	}
420}
421
422impl<
423		S1: PartialEq<S2>,
424		P1: PartialEq<P2>,
425		O1: PartialEq<O2>,
426		G1: PartialEq<G2>,
427		S2,
428		P2,
429		O2,
430		G2,
431	> PartialEq<Quad<S2, P2, O2, G2>> for Quad<S1, P1, O1, G1>
432{
433	fn eq(&self, other: &Quad<S2, P2, O2, G2>) -> bool {
434		self.0 == other.0
435			&& self.1 == other.1
436			&& self.2 == other.2
437			&& match (&self.3, &other.3) {
438				(Some(a), Some(b)) => a == b,
439				(None, None) => true,
440				_ => false,
441			}
442	}
443}
444
445impl<
446		S1: PartialOrd<S2>,
447		P1: PartialOrd<P2>,
448		O1: PartialOrd<O2>,
449		G1: PartialOrd<G2>,
450		S2,
451		P2,
452		O2,
453		G2,
454	> PartialOrd<Quad<S2, P2, O2, G2>> for Quad<S1, P1, O1, G1>
455{
456	fn partial_cmp(&self, other: &Quad<S2, P2, O2, G2>) -> Option<Ordering> {
457		match self.0.partial_cmp(&other.0) {
458			Some(Ordering::Equal) => match self.1.partial_cmp(&other.1) {
459				Some(Ordering::Equal) => match self.2.partial_cmp(&other.2) {
460					Some(Ordering::Equal) => match (&self.3, &other.3) {
461						(Some(a), Some(b)) => a.partial_cmp(b),
462						(Some(_), None) => Some(Ordering::Greater),
463						(None, Some(_)) => Some(Ordering::Less),
464						(None, None) => Some(Ordering::Equal),
465					},
466					cmp => cmp,
467				},
468				cmp => cmp,
469			},
470			cmp => cmp,
471		}
472	}
473}
474
475impl<S: RdfDisplay, P: RdfDisplay, O: RdfDisplay, G: RdfDisplay> fmt::Display for Quad<S, P, O, G> {
476	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
477		match self.graph() {
478			Some(graph) => write!(
479				f,
480				"{} {} {} {}",
481				self.0.rdf_display(),
482				self.1.rdf_display(),
483				self.2.rdf_display(),
484				graph.rdf_display()
485			),
486			None => write!(
487				f,
488				"{} {} {}",
489				self.0.rdf_display(),
490				self.1.rdf_display(),
491				self.2.rdf_display()
492			),
493		}
494	}
495}
496
497impl<S: RdfDisplay, P: RdfDisplay, O: RdfDisplay, G: RdfDisplay> RdfDisplay for Quad<S, P, O, G> {
498	fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
499		match self.graph() {
500			Some(graph) => write!(
501				f,
502				"{} {} {} {}",
503				self.0.rdf_display(),
504				self.1.rdf_display(),
505				self.2.rdf_display(),
506				graph.rdf_display()
507			),
508			None => write!(
509				f,
510				"{} {} {}",
511				self.0.rdf_display(),
512				self.1.rdf_display(),
513				self.2.rdf_display()
514			),
515		}
516	}
517}
518
519#[cfg(feature = "contextual")]
520impl<
521		S: RdfDisplayWithContext<V>,
522		P: RdfDisplayWithContext<V>,
523		O: RdfDisplayWithContext<V>,
524		G: RdfDisplayWithContext<V>,
525		V,
526	> DisplayWithContext<V> for Quad<S, P, O, G>
527{
528	fn fmt_with(&self, vocabulary: &V, f: &mut fmt::Formatter) -> fmt::Result {
529		match self.graph() {
530			Some(graph) => write!(
531				f,
532				"{} {} {} {}",
533				self.0.with(vocabulary).rdf_display(),
534				self.1.with(vocabulary).rdf_display(),
535				self.2.with(vocabulary).rdf_display(),
536				graph.with(vocabulary).rdf_display()
537			),
538			None => write!(
539				f,
540				"{} {} {}",
541				self.0.with(vocabulary).rdf_display(),
542				self.1.with(vocabulary).rdf_display(),
543				self.2.with(vocabulary).rdf_display()
544			),
545		}
546	}
547}
548
549#[cfg(feature = "contextual")]
550impl<
551		S: RdfDisplayWithContext<V>,
552		P: RdfDisplayWithContext<V>,
553		O: RdfDisplayWithContext<V>,
554		G: RdfDisplayWithContext<V>,
555		V,
556	> RdfDisplayWithContext<V> for Quad<S, P, O, G>
557{
558	fn rdf_fmt_with(&self, vocabulary: &V, f: &mut fmt::Formatter) -> fmt::Result {
559		match self.graph() {
560			Some(graph) => write!(
561				f,
562				"{} {} {} {}",
563				self.0.with(vocabulary).rdf_display(),
564				self.1.with(vocabulary).rdf_display(),
565				self.2.with(vocabulary).rdf_display(),
566				graph.with(vocabulary).rdf_display()
567			),
568			None => write!(
569				f,
570				"{} {} {}",
571				self.0.with(vocabulary).rdf_display(),
572				self.1.with(vocabulary).rdf_display(),
573				self.2.with(vocabulary).rdf_display()
574			),
575		}
576	}
577}