Skip to main content

rdf_syntax/term/ground/
cow.rs

1use core::fmt;
2use std::borrow::Cow;
3use std::cmp::Ordering;
4
5use into_owned_trait::IntoOwned;
6use iref::{Iri, IriBuf};
7
8use crate::{CowLiteral, CowLiteralType, Literal, LiteralRef, RdfDisplay, XSD_STRING};
9
10use super::{GroundTerm, GroundTermRef};
11
12/// Copy-on-write ground term.
13///
14/// A [`GroundTerm`] that is either borrowed or owned.
15#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
16pub enum CowGroundTerm<'a> {
17	/// IRI.
18	Iri(Cow<'a, Iri>),
19
20	/// Literal value.
21	Literal(CowLiteral<'a>),
22}
23
24impl CowGroundTerm<'_> {
25	/// Checks if this is an IRI.
26	pub fn is_iri(&self) -> bool {
27		matches!(self, Self::Iri(_))
28	}
29
30	/// Checks if this is a literal.
31	pub fn is_literal(&self) -> bool {
32		matches!(self, Self::Literal(_))
33	}
34
35	/// Returns this ground term as an IRI, if it is one.
36	pub fn as_iri(&self) -> Option<&Iri> {
37		match self {
38			Self::Iri(iri) => Some(iri),
39			_ => None,
40		}
41	}
42
43	/// Returns this ground term as a literal, if it is one.
44	pub fn as_literal(&self) -> Option<LiteralRef<'_>> {
45		match self {
46			Self::Literal(l) => Some(l.as_ref()),
47			_ => None,
48		}
49	}
50
51	/// Returns a reference to this ground term.
52	pub fn as_ref(&self) -> GroundTermRef<'_> {
53		match self {
54			Self::Iri(iri) => GroundTermRef::Iri(iri),
55			Self::Literal(l) => GroundTermRef::Literal(l.as_ref()),
56		}
57	}
58
59	/// Clones the ground term, if needed, to get rid of the borrow.
60	pub fn into_owned(self) -> GroundTerm {
61		match self {
62			Self::Iri(iri) => GroundTerm::Iri(iri.into_owned()),
63			Self::Literal(l) => GroundTerm::Literal(l.into_owned()),
64		}
65	}
66}
67
68impl<'a> CowGroundTerm<'a> {
69	/// Turns this ground term into a literal, if it is one.
70	pub fn into_literal(self) -> Option<CowLiteral<'a>> {
71		match self {
72			Self::Literal(l) => Some(l),
73			_ => None,
74		}
75	}
76
77	/// Turns this ground term into a literal, or returns the IRI if it isn't
78	/// one.
79	pub fn try_into_literal(self) -> Result<CowLiteral<'a>, Cow<'a, Iri>> {
80		match self {
81			Self::Literal(l) => Ok(l),
82			Self::Iri(iri) => Err(iri),
83		}
84	}
85
86	/// Turns this ground term into an IRI, if it is one.
87	pub fn into_iri(self) -> Option<Cow<'a, Iri>> {
88		match self {
89			Self::Iri(iri) => Some(iri),
90			_ => None,
91		}
92	}
93
94	/// Turns this ground term into an IRI, or returns it unchanged if it
95	/// isn't one.
96	pub fn try_into_iri(self) -> Result<Cow<'a, Iri>, Self> {
97		match self {
98			Self::Iri(iri) => Ok(iri),
99			other => Err(other),
100		}
101	}
102}
103
104impl From<GroundTerm> for CowGroundTerm<'_> {
105	fn from(value: GroundTerm) -> Self {
106		value.into_cow()
107	}
108}
109
110impl<'a> From<&'a GroundTerm> for CowGroundTerm<'a> {
111	fn from(value: &'a GroundTerm) -> Self {
112		value.as_cow()
113	}
114}
115
116impl<'a> From<GroundTermRef<'a>> for CowGroundTerm<'a> {
117	fn from(value: GroundTermRef<'a>) -> Self {
118		value.into_cow()
119	}
120}
121
122impl From<CowGroundTerm<'_>> for GroundTerm {
123	fn from(value: CowGroundTerm<'_>) -> Self {
124		value.into_owned()
125	}
126}
127
128impl IntoOwned for CowGroundTerm<'_> {
129	type Owned = GroundTerm;
130
131	fn into_owned(self) -> GroundTerm {
132		match self {
133			Self::Iri(iri) => GroundTerm::Iri(iri.into_owned()),
134			Self::Literal(l) => GroundTerm::Literal(l.into_owned()),
135		}
136	}
137}
138
139impl equivalent::Equivalent<GroundTerm> for CowGroundTerm<'_> {
140	fn equivalent(&self, key: &GroundTerm) -> bool {
141		self == key
142	}
143}
144
145impl equivalent::Comparable<GroundTerm> for CowGroundTerm<'_> {
146	fn compare(&self, key: &GroundTerm) -> std::cmp::Ordering {
147		self.partial_cmp(key).unwrap()
148	}
149}
150
151impl<'a> From<CowLiteral<'a>> for CowGroundTerm<'a> {
152	fn from(value: CowLiteral<'a>) -> Self {
153		Self::Literal(value)
154	}
155}
156
157impl<'a> From<&'a Literal> for CowGroundTerm<'a> {
158	fn from(value: &'a Literal) -> Self {
159		Self::Literal(value.into())
160	}
161}
162
163impl<'a> From<LiteralRef<'a>> for CowGroundTerm<'a> {
164	fn from(value: LiteralRef<'a>) -> Self {
165		Self::Literal(value.into())
166	}
167}
168
169impl<'a> From<&'a Iri> for CowGroundTerm<'a> {
170	fn from(value: &'a Iri) -> Self {
171		Self::Iri(Cow::Borrowed(value))
172	}
173}
174
175impl<'a> From<&'a IriBuf> for CowGroundTerm<'a> {
176	fn from(value: &'a IriBuf) -> Self {
177		Self::Iri(Cow::Borrowed(value))
178	}
179}
180
181impl<'a> From<&'a str> for CowGroundTerm<'a> {
182	fn from(value: &'a str) -> Self {
183		Self::Literal(CowLiteral::new(
184			value,
185			CowLiteralType::Any(Cow::Borrowed(XSD_STRING)),
186		))
187	}
188}
189
190impl<'a> From<&'a String> for CowGroundTerm<'a> {
191	fn from(value: &'a String) -> Self {
192		value.as_str().into()
193	}
194}
195
196impl PartialEq<GroundTerm> for CowGroundTerm<'_> {
197	fn eq(&self, other: &GroundTerm) -> bool {
198		self.as_ref() == *other
199	}
200}
201
202impl PartialEq<CowGroundTerm<'_>> for GroundTerm {
203	fn eq(&self, other: &CowGroundTerm<'_>) -> bool {
204		*self == other.as_ref()
205	}
206}
207
208impl<'a> PartialEq<GroundTermRef<'a>> for CowGroundTerm<'_> {
209	fn eq(&self, other: &GroundTermRef<'a>) -> bool {
210		self.as_ref() == *other
211	}
212}
213
214impl PartialEq<CowGroundTerm<'_>> for GroundTermRef<'_> {
215	fn eq(&self, other: &CowGroundTerm<'_>) -> bool {
216		*self == other.as_ref()
217	}
218}
219
220impl PartialOrd<GroundTerm> for CowGroundTerm<'_> {
221	fn partial_cmp(&self, other: &GroundTerm) -> Option<Ordering> {
222		self.as_ref().partial_cmp(other)
223	}
224}
225
226impl PartialOrd<CowGroundTerm<'_>> for GroundTerm {
227	fn partial_cmp(&self, other: &CowGroundTerm<'_>) -> Option<Ordering> {
228		self.partial_cmp(&other.as_ref())
229	}
230}
231
232impl<'a> PartialOrd<GroundTermRef<'a>> for CowGroundTerm<'_> {
233	fn partial_cmp(&self, other: &GroundTermRef<'a>) -> Option<Ordering> {
234		self.as_ref().partial_cmp(other)
235	}
236}
237
238impl PartialOrd<CowGroundTerm<'_>> for GroundTermRef<'_> {
239	fn partial_cmp(&self, other: &CowGroundTerm<'_>) -> Option<Ordering> {
240		self.partial_cmp(&other.as_ref())
241	}
242}
243
244impl From<GroundTermRef<'_>> for GroundTerm {
245	fn from(value: GroundTermRef<'_>) -> Self {
246		value.to_owned()
247	}
248}
249
250impl fmt::Display for CowGroundTerm<'_> {
251	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
252		match self {
253			Self::Iri(iri) => iri.fmt(f),
254			Self::Literal(lit) => lit.fmt(f),
255		}
256	}
257}
258
259impl RdfDisplay for CowGroundTerm<'_> {
260	fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
261		match self {
262			Self::Iri(iri) => iri.rdf_fmt(f),
263			Self::Literal(lit) => lit.rdf_fmt(f),
264		}
265	}
266}