Skip to main content

rdf_syntax/term/ground/
mod.rs

1use std::cmp::Ordering;
2use std::hash::Hash;
3use std::{borrow::Cow, fmt};
4
5use iref::{Iri, IriBuf};
6
7use crate::{Literal, LiteralRef, RdfDisplay};
8
9mod cow;
10mod r#ref;
11
12pub use cow::*;
13pub use r#ref::*;
14
15/// Term excluding blank node identifiers.
16#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
17#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
18#[cfg_attr(feature = "serde", serde(untagged))]
19pub enum GroundTerm {
20	/// IRI.
21	Iri(IriBuf),
22
23	/// Literal value.
24	Literal(Literal),
25}
26
27impl GroundTerm {
28	/// Checks if this is an IRI.
29	pub fn is_iri(&self) -> bool {
30		matches!(self, Self::Iri(_))
31	}
32
33	/// Checks if this is a literal.
34	pub fn is_literal(&self) -> bool {
35		matches!(self, Self::Literal(_))
36	}
37
38	/// Returns this ground term as a literal, if it is one.
39	pub fn as_literal(&self) -> Option<LiteralRef<'_>> {
40		match self {
41			Self::Literal(lit) => Some(lit.as_ref()),
42			_ => None,
43		}
44	}
45
46	/// Turns this ground term into a literal, if it is one.
47	pub fn into_literal(self) -> Option<Literal> {
48		match self {
49			Self::Literal(lit) => Some(lit),
50			_ => None,
51		}
52	}
53
54	/// Turns this ground term into a literal, or returns the IRI if it isn't
55	/// one.
56	pub fn try_into_literal(self) -> Result<Literal, IriBuf> {
57		match self {
58			Self::Literal(lit) => Ok(lit),
59			Self::Iri(id) => Err(id),
60		}
61	}
62
63	/// Returns this ground term as an IRI, if it is one.
64	pub fn as_iri(&self) -> Option<&Iri> {
65		match self {
66			Self::Iri(id) => Some(id),
67			_ => None,
68		}
69	}
70
71	/// Turns this ground term into an IRI, or returns it unchanged if it
72	/// isn't one.
73	pub fn try_into_iri(self) -> Result<IriBuf, Self> {
74		match self {
75			Self::Iri(iri) => Ok(iri),
76			other => Err(other),
77		}
78	}
79
80	/// Turns this ground term into an IRI, if it is one.
81	pub fn into_iri(self) -> Option<IriBuf> {
82		self.try_into_iri().ok()
83	}
84
85	/// Returns a reference to this ground term.
86	pub fn as_ref(&self) -> GroundTermRef<'_> {
87		match self {
88			Self::Iri(id) => GroundTermRef::Iri(id),
89			Self::Literal(l) => GroundTermRef::Literal(l.as_ref()),
90		}
91	}
92
93	/// Returns a copy-on-write reference to this ground term.
94	pub fn as_cow(&self) -> CowGroundTerm<'_> {
95		match self {
96			Self::Iri(id) => CowGroundTerm::Iri(Cow::Borrowed(id)),
97			Self::Literal(l) => CowGroundTerm::Literal(l.as_cow()),
98		}
99	}
100
101	/// Turns this ground term into a copy-on-write ground term.
102	pub fn into_cow(self) -> CowGroundTerm<'static> {
103		match self {
104			Self::Iri(id) => CowGroundTerm::Iri(Cow::Owned(id)),
105			Self::Literal(l) => CowGroundTerm::Literal(l.into_cow()),
106		}
107	}
108}
109
110impl Hash for GroundTerm {
111	fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
112		match self {
113			Self::Iri(id) => id.hash(state),
114			Self::Literal(l) => l.hash(state),
115		}
116	}
117}
118
119impl fmt::Display for GroundTerm {
120	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
121		match self {
122			Self::Iri(id) => id.fmt(f),
123			Self::Literal(lit) => lit.fmt(f),
124		}
125	}
126}
127
128impl RdfDisplay for GroundTerm {
129	fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
130		match self {
131			Self::Iri(id) => id.rdf_fmt(f),
132			Self::Literal(lit) => lit.rdf_fmt(f),
133		}
134	}
135}
136
137impl<'a> PartialEq<GroundTermRef<'a>> for GroundTerm {
138	fn eq(&self, other: &GroundTermRef<'a>) -> bool {
139		match (self, other) {
140			(Self::Iri(a), GroundTermRef::Iri(b)) => a == *b,
141			(Self::Literal(a), GroundTermRef::Literal(b)) => a == b,
142			_ => false,
143		}
144	}
145}
146
147impl<'a> PartialOrd<GroundTermRef<'a>> for GroundTerm {
148	fn partial_cmp(&self, other: &GroundTermRef<'a>) -> Option<Ordering> {
149		match (self, other) {
150			(Self::Iri(a), GroundTermRef::Iri(b)) => (*a).partial_cmp(b),
151			(Self::Iri(_), GroundTermRef::Literal(_)) => Some(Ordering::Less),
152			(Self::Literal(_), GroundTermRef::Iri(_)) => Some(Ordering::Greater),
153			(Self::Literal(a), GroundTermRef::Literal(b)) => (*a).partial_cmp(b),
154		}
155	}
156}