rdf_types/term/
mod.rs

1use crate::interpretation::{Interpret, LiteralInterpretationMut};
2use crate::vocabulary::{
3	ByRef, EmbedIntoVocabulary, EmbeddedIntoVocabulary, ExtractFromVocabulary,
4	ExtractedFromVocabulary, LiteralVocabulary, TryExtractFromVocabulary,
5};
6use crate::{BlankIdBuf, Literal, RdfDisplay};
7use iref::IriBuf;
8use std::fmt;
9use std::{cmp::Ordering, hash::Hash};
10
11mod id;
12mod into;
13mod maybe_blank;
14mod maybe_iri;
15
16pub use id::*;
17pub use into::*;
18pub use maybe_blank::*;
19pub use maybe_iri::*;
20// pub use maybe_literal::*;
21
22#[cfg(feature = "contextual")]
23use contextual::{AsRefWithContext, DisplayWithContext};
24
25/// gRDF term.
26///
27/// Either a node identifier or a literal value.
28///
29/// # `Hash` implementation
30///
31/// It is guaranteed that the `Hash` implementation of `Term` is *transparent*,
32/// meaning that the hash of `Term::Id(id)` the same as `id` and the hash of
33/// `Term::Literal(l)` is the same as `l`.
34#[derive(Clone, Copy, Eq, Ord, Debug)]
35#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
36pub enum Term<I = Id, L = Literal> {
37	/// Node identifier.
38	Id(I),
39
40	/// Literal value.
41	Literal(L),
42}
43
44/// Lexical RDF term reference.
45pub type LexicalTermRef<'a> = Term<LexicalIdRef<'a>, &'a Literal>;
46
47impl<I: Hash, L: Hash> Hash for Term<I, L> {
48	fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
49		match self {
50			Self::Id(id) => id.hash(state),
51			Self::Literal(l) => l.hash(state),
52		}
53	}
54}
55
56impl<I, L> Term<I, L> {
57	pub fn blank(id: I::BlankId) -> Self
58	where
59		I: FromBlankId,
60	{
61		Self::Id(I::from_blank(id))
62	}
63
64	pub fn iri(iri: I::Iri) -> Self
65	where
66		I: FromIri,
67	{
68		Self::Id(I::from_iri(iri))
69	}
70
71	pub fn is_id(&self) -> bool {
72		matches!(self, Self::Id(_))
73	}
74
75	pub fn is_literal(&self) -> bool {
76		matches!(self, Self::Literal(_))
77	}
78
79	pub fn as_id(&self) -> Option<&I> {
80		match self {
81			Self::Id(id) => Some(id),
82			_ => None,
83		}
84	}
85
86	pub fn into_id(self) -> Option<I> {
87		match self {
88			Self::Id(id) => Some(id),
89			_ => None,
90		}
91	}
92
93	pub fn try_into_id(self) -> Result<I, L> {
94		match self {
95			Self::Id(id) => Ok(id),
96			Self::Literal(l) => Err(l),
97		}
98	}
99
100	pub fn as_literal(&self) -> Option<&L> {
101		match self {
102			Self::Literal(lit) => Some(lit),
103			_ => None,
104		}
105	}
106
107	pub fn into_literal(self) -> Option<L> {
108		match self {
109			Self::Literal(lit) => Some(lit),
110			_ => None,
111		}
112	}
113
114	pub fn try_into_literal(self) -> Result<L, I> {
115		match self {
116			Self::Literal(lit) => Ok(lit),
117			Self::Id(id) => Err(id),
118		}
119	}
120
121	pub fn is_blank(&self) -> bool
122	where
123		I: TryAsBlankId,
124	{
125		match self {
126			Self::Id(id) => id.is_blank(),
127			Self::Literal(_) => false,
128		}
129	}
130
131	pub fn is_iri(&self) -> bool
132	where
133		I: TryAsIri,
134	{
135		match self {
136			Self::Id(id) => id.is_iri(),
137			Self::Literal(_) => false,
138		}
139	}
140
141	pub fn as_blank(&self) -> Option<&I::BlankId>
142	where
143		I: TryAsBlankId,
144	{
145		match self {
146			Self::Id(id) => id.try_as_blank(),
147			_ => None,
148		}
149	}
150
151	pub fn try_into_blank(self) -> Result<I::BlankId, Self>
152	where
153		I: TryIntoBlankId,
154	{
155		match self {
156			Self::Id(id) => id.try_into_blank().map_err(Self::Id),
157			other => Err(other),
158		}
159	}
160
161	pub fn into_blank(self) -> Option<I::BlankId>
162	where
163		I: TryIntoBlankId,
164	{
165		self.try_into_blank().ok()
166	}
167
168	pub fn as_iri(&self) -> Option<&I::Iri>
169	where
170		I: TryAsIri,
171	{
172		match self {
173			Self::Id(id) => id.try_as_iri(),
174			_ => None,
175		}
176	}
177
178	pub fn try_into_iri(self) -> Result<I::Iri, Self>
179	where
180		I: TryIntoIri,
181	{
182		match self {
183			Self::Id(id) => id.try_into_iri().map_err(Self::Id),
184			other => Err(other),
185		}
186	}
187
188	pub fn into_iri(self) -> Option<I::Iri>
189	where
190		I: TryIntoIri,
191	{
192		self.try_into_iri().ok()
193	}
194
195	/// Converts from `&Term<I, L>` to `Term<&I, &L>`.
196	pub fn as_ref(&self) -> Term<&I, &L> {
197		match self {
198			Self::Id(id) => Term::Id(id),
199			Self::Literal(l) => Term::Literal(l),
200		}
201	}
202}
203
204impl<I: LiteralInterpretationMut<L>, T: Interpret<I, Interpreted = I::Resource>, L> Interpret<I>
205	for Term<T, L>
206{
207	type Interpreted = I::Resource;
208
209	fn interpret(self, interpretation: &mut I) -> Self::Interpreted {
210		match self {
211			Self::Id(id) => id.interpret(interpretation),
212			Self::Literal(l) => interpretation.interpret_literal(l),
213		}
214	}
215}
216
217impl<V: LiteralVocabulary, I: ExtractedFromVocabulary<V>> ExtractedFromVocabulary<V>
218	for Term<I, V::Literal>
219{
220	type Extracted = Term<I::Extracted, Literal>;
221
222	fn extracted_from_vocabulary(&self, vocabulary: &V) -> Self::Extracted {
223		match self {
224			Self::Id(i) => Term::Id(i.extracted_from_vocabulary(vocabulary)),
225			Self::Literal(l) => Term::Literal(
226				vocabulary
227					.literal(l)
228					.unwrap()
229					.extract_from_vocabulary(vocabulary),
230			),
231		}
232	}
233}
234
235impl<V: LiteralVocabulary, I: ExtractFromVocabulary<V>> ExtractFromVocabulary<V>
236	for Term<I, V::Literal>
237{
238	type Extracted = Term<I::Extracted, Literal>;
239
240	fn extract_from_vocabulary(self, vocabulary: &V) -> Self::Extracted {
241		match self {
242			Self::Id(i) => Term::Id(i.extract_from_vocabulary(vocabulary)),
243			Self::Literal(l) => Term::Literal(
244				vocabulary
245					.owned_literal(l)
246					.ok()
247					.unwrap()
248					.extract_from_vocabulary(vocabulary),
249			),
250		}
251	}
252}
253
254impl<V: LiteralVocabulary, I> ExtractFromVocabulary<V> for ByRef<Term<I, &V::Literal>>
255where
256	ByRef<I>: ExtractFromVocabulary<V>,
257{
258	type Extracted = Term<<ByRef<I> as ExtractFromVocabulary<V>>::Extracted, Literal>;
259
260	fn extract_from_vocabulary(self, vocabulary: &V) -> Self::Extracted {
261		match self.0 {
262			Term::Id(i) => Term::Id(ByRef(i).extract_from_vocabulary(vocabulary)),
263			Term::Literal(l) => Term::Literal(
264				vocabulary
265					.literal(l)
266					.unwrap()
267					.extract_from_vocabulary(vocabulary),
268			),
269		}
270	}
271}
272
273impl<V, I: TryExtractFromVocabulary<V>, L: TryExtractFromVocabulary<V>> TryExtractFromVocabulary<V>
274	for Term<I, L>
275{
276	type Extracted = Term<I::Extracted, L::Extracted>;
277
278	type Error = Term<I::Error, L::Error>;
279
280	fn try_extract_from_vocabulary(self, vocabulary: &V) -> Result<Self::Extracted, Self::Error> {
281		match self {
282			Self::Id(i) => i
283				.try_extract_from_vocabulary(vocabulary)
284				.map_err(Term::Id)
285				.map(Term::Id),
286			Self::Literal(l) => l
287				.try_extract_from_vocabulary(vocabulary)
288				.map_err(Term::Literal)
289				.map(Term::Literal),
290		}
291	}
292}
293
294impl<'a, I, L> Term<&'a I, &'a L> {
295	pub fn cloned(self) -> Term<I, L>
296	where
297		I: Clone,
298		L: Clone,
299	{
300		match self {
301			Self::Id(id) => Term::Id(id.clone()),
302			Self::Literal(l) => Term::Literal(l.clone()),
303		}
304	}
305
306	pub fn copied(self) -> Term<I, L>
307	where
308		I: Copy,
309		L: Copy,
310	{
311		match self {
312			Self::Id(id) => Term::Id(*id),
313			Self::Literal(l) => Term::Literal(*l),
314		}
315	}
316}
317
318impl Term {
319	#[inline(always)]
320	pub fn as_lexical_term_ref(&self) -> LexicalTermRef {
321		match self {
322			Self::Id(id) => Term::Id(id.as_lexical_id_ref()),
323			Self::Literal(l) => Term::Literal(l),
324		}
325	}
326
327	/// Alias for [`Self::as_lexical_term_ref`].
328	#[inline(always)]
329	pub fn as_lexical_object_ref(&self) -> LexicalObjectRef {
330		self.as_lexical_term_ref()
331	}
332}
333
334impl<V, I: EmbedIntoVocabulary<V>, L: EmbedIntoVocabulary<V>> EmbedIntoVocabulary<V>
335	for Term<I, L>
336{
337	type Embedded = Term<I::Embedded, L::Embedded>;
338
339	fn embed_into_vocabulary(self, vocabulary: &mut V) -> Self::Embedded {
340		match self {
341			Self::Id(id) => Term::Id(id.embed_into_vocabulary(vocabulary)),
342			Self::Literal(l) => Term::Literal(l.embed_into_vocabulary(vocabulary)),
343		}
344	}
345}
346
347impl<V, I: EmbeddedIntoVocabulary<V>, L: EmbeddedIntoVocabulary<V>> EmbeddedIntoVocabulary<V>
348	for Term<I, L>
349{
350	type Embedded = Term<I::Embedded, L::Embedded>;
351
352	fn embedded_into_vocabulary(&self, vocabulary: &mut V) -> Self::Embedded {
353		match self {
354			Self::Id(id) => Term::Id(id.embedded_into_vocabulary(vocabulary)),
355			Self::Literal(l) => Term::Literal(l.embedded_into_vocabulary(vocabulary)),
356		}
357	}
358}
359
360impl<I1: PartialEq<I2>, L1: PartialEq<L2>, I2, L2> PartialEq<Term<I2, L2>> for Term<I1, L1> {
361	fn eq(&self, other: &Term<I2, L2>) -> bool {
362		match (self, other) {
363			(Self::Id(a), Term::Id(b)) => a == b,
364			(Self::Literal(a), Term::Literal(b)) => a == b,
365			_ => false,
366		}
367	}
368}
369
370impl<I1: PartialOrd<I2>, L1: PartialOrd<L2>, I2, L2> PartialOrd<Term<I2, L2>> for Term<I1, L1> {
371	fn partial_cmp(&self, other: &Term<I2, L2>) -> Option<Ordering> {
372		match (self, other) {
373			(Self::Id(a), Term::Id(b)) => a.partial_cmp(b),
374			(Self::Id(_), Term::Literal(_)) => Some(Ordering::Less),
375			(Self::Literal(a), Term::Literal(b)) => a.partial_cmp(b),
376			(Self::Literal(_), Term::Id(_)) => Some(Ordering::Greater),
377		}
378	}
379}
380
381impl<I: fmt::Display, L: fmt::Display> fmt::Display for Term<I, L> {
382	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
383		match self {
384			Self::Id(id) => id.fmt(f),
385			Self::Literal(lit) => lit.fmt(f),
386		}
387	}
388}
389
390impl<I: RdfDisplay, L: RdfDisplay> RdfDisplay for Term<I, L> {
391	fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
392		match self {
393			Self::Id(id) => id.rdf_fmt(f),
394			Self::Literal(lit) => lit.rdf_fmt(f),
395		}
396	}
397}
398
399#[cfg(feature = "contextual")]
400impl<I: DisplayWithContext<V>, L: DisplayWithContext<V>, V> DisplayWithContext<V> for Term<I, L> {
401	fn fmt_with(&self, vocabulary: &V, f: &mut fmt::Formatter) -> fmt::Result {
402		match self {
403			Self::Id(id) => id.fmt_with(vocabulary, f),
404			Self::Literal(lit) => lit.fmt_with(vocabulary, f),
405		}
406	}
407}
408
409#[cfg(feature = "contextual")]
410impl<I: crate::RdfDisplayWithContext<V>, L: crate::RdfDisplayWithContext<V>, V>
411	crate::RdfDisplayWithContext<V> for Term<I, L>
412{
413	fn rdf_fmt_with(&self, vocabulary: &V, f: &mut fmt::Formatter) -> fmt::Result {
414		match self {
415			Self::Id(id) => id.rdf_fmt_with(vocabulary, f),
416			Self::Literal(lit) => lit.rdf_fmt_with(vocabulary, f),
417		}
418	}
419}
420
421#[cfg(feature = "contextual")]
422impl<I: AsRefWithContext<str, V>, L: AsRef<str>, V> AsRefWithContext<str, V> for Term<I, L> {
423	fn as_ref_with<'a>(&'a self, vocabulary: &'a V) -> &'a str {
424		match self {
425			Self::Id(id) => id.as_ref_with(vocabulary),
426			Self::Literal(l) => l.as_ref(),
427		}
428	}
429}
430
431impl LexicalTermRef<'_> {
432	pub fn into_owned(self) -> Term {
433		match self {
434			Self::Id(id) => Term::Id(id.into_owned()),
435			Self::Literal(l) => Term::Literal(l.clone()),
436		}
437	}
438}
439
440/// RDF triple/quad subject.
441pub type Subject<I = IriBuf, B = BlankIdBuf> = Id<I, B>;
442
443/// Lexical RDF subject reference.
444pub type LexicalSubjectRef<'a> = LexicalIdRef<'a>;
445
446/// RDF triple/quad object.
447pub type Object<I = Id, L = Literal> = Term<I, L>;
448
449/// Lexical RDF object reference.
450pub type LexicalObjectRef<'a> = LexicalTermRef<'a>;
451
452/// RDF quad graph Label.
453pub type GraphLabel<I = IriBuf, B = BlankIdBuf> = Id<I, B>;
454
455/// Lexical RDF graph label reference.
456pub type LexicalGraphLabelRef<'a> = LexicalIdRef<'a>;
457
458/// Type that can be interpreted as an RDF term.
459pub trait AsRdfTerm<I, B, L> {
460	/// Returns this value as an RDF term.
461	fn as_rdf_term(&self) -> Term<Id<&I, &B>, &L>;
462}
463
464impl<I, B, L> AsRdfTerm<I, B, L> for Id<I, B> {
465	fn as_rdf_term(&self) -> Term<Id<&I, &B>, &L> {
466		Term::Id(self.as_ref())
467	}
468}
469
470impl<I, B, L> AsRdfTerm<I, B, L> for Term<Id<I, B>, L> {
471	fn as_rdf_term(&self) -> Term<Id<&I, &B>, &L> {
472		match self {
473			Self::Id(id) => Term::Id(id.as_ref()),
474			Self::Literal(l) => Term::Literal(l),
475		}
476	}
477}