1use core::fmt;
2use std::borrow::Cow;
3use std::cmp::Ordering;
4
5use into_owned_trait::IntoOwned;
6use iref::{Iri, IriBuf};
7
8use crate::{
9 BlankId, BlankIdBuf, CowId, CowLiteral, GroundTerm, Id, IdRef, Literal, LiteralRef, RdfDisplay,
10 TermRef,
11};
12
13use super::{CowGroundTerm, Term};
14
15#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
17pub enum CowTerm<'a> {
18 BlankId(Cow<'a, BlankId>),
20
21 Ground(CowGroundTerm<'a>),
23}
24
25impl CowTerm<'_> {
26 pub fn is_id(&self) -> bool {
29 matches!(self, Self::BlankId(_) | Self::Ground(CowGroundTerm::Iri(_)))
30 }
31
32 pub fn as_id(&self) -> Option<IdRef<'_>> {
34 match self {
35 Self::BlankId(b) => Some(IdRef::BlankId(b)),
36 Self::Ground(CowGroundTerm::Iri(iri)) => Some(IdRef::Iri(iri)),
37 _ => None,
38 }
39 }
40
41 pub fn is_blank_id(&self) -> bool {
43 matches!(self, Self::BlankId(_))
44 }
45
46 pub fn is_ground(&self) -> bool {
49 matches!(self, Self::Ground(_))
50 }
51
52 pub fn is_iri(&self) -> bool {
54 matches!(self, Self::Ground(CowGroundTerm::Iri(_)))
55 }
56
57 pub fn is_literal(&self) -> bool {
59 matches!(self, Self::Ground(CowGroundTerm::Literal(_)))
60 }
61
62 pub fn as_blank_id(&self) -> Option<&BlankId> {
64 match self {
65 Self::BlankId(b) => Some(b),
66 _ => None,
67 }
68 }
69
70 pub fn as_iri(&self) -> Option<&Iri> {
72 match self {
73 Self::Ground(g) => g.as_iri(),
74 _ => None,
75 }
76 }
77
78 pub fn as_ground(&self) -> Option<&CowGroundTerm<'_>> {
80 match self {
81 Self::Ground(g) => Some(g),
82 _ => None,
83 }
84 }
85
86 pub fn as_literal(&self) -> Option<LiteralRef<'_>> {
88 match self {
89 Self::Ground(g) => g.as_literal(),
90 _ => None,
91 }
92 }
93
94 pub fn as_ref(&self) -> TermRef<'_> {
96 match self {
97 Self::BlankId(b) => TermRef::BlankId(b),
98 Self::Ground(g) => TermRef::Ground(g.as_ref()),
99 }
100 }
101
102 pub fn into_owned(self) -> Term {
104 match self {
105 Self::BlankId(b) => Term::BlankId(b.into_owned()),
106 Self::Ground(t) => Term::Ground(t.into_owned()),
107 }
108 }
109}
110
111impl<'a> CowTerm<'a> {
112 pub fn into_ground(self) -> Result<CowGroundTerm<'a>, Cow<'a, BlankId>> {
115 match self {
116 Self::Ground(g) => Ok(g),
117 Self::BlankId(b) => Err(b),
118 }
119 }
120
121 pub fn into_id(self) -> Result<CowId<'a>, CowLiteral<'a>> {
124 match self {
125 Self::BlankId(b) => Ok(CowId::BlankId(b)),
126 Self::Ground(CowGroundTerm::Iri(iri)) => Ok(CowId::Iri(iri)),
127 Self::Ground(CowGroundTerm::Literal(lit)) => Err(lit),
128 }
129 }
130}
131
132impl<'a> From<TermRef<'a>> for CowTerm<'a> {
133 fn from(value: TermRef<'a>) -> Self {
134 value.into_cow()
135 }
136}
137
138impl From<CowTerm<'_>> for Term {
139 fn from(value: CowTerm<'_>) -> Self {
140 value.into_owned()
141 }
142}
143
144impl IntoOwned for CowTerm<'_> {
145 type Owned = Term;
146
147 fn into_owned(self) -> Term {
148 match self {
149 Self::BlankId(b) => Term::BlankId(b.into_owned()),
150 Self::Ground(t) => Term::Ground(t.into_owned()),
151 }
152 }
153}
154
155impl equivalent::Equivalent<Term> for CowTerm<'_> {
156 fn equivalent(&self, key: &Term) -> bool {
157 self == key
158 }
159}
160
161impl equivalent::Comparable<Term> for CowTerm<'_> {
162 fn compare(&self, key: &Term) -> std::cmp::Ordering {
163 self.partial_cmp(key).unwrap()
164 }
165}
166
167impl From<GroundTerm> for CowTerm<'_> {
168 fn from(value: GroundTerm) -> Self {
169 Self::Ground(value.into())
170 }
171}
172
173impl From<Term> for CowTerm<'_> {
174 fn from(value: Term) -> Self {
175 value.into_cow()
176 }
177}
178
179impl<'a> From<&'a Term> for CowTerm<'a> {
180 fn from(value: &'a Term) -> Self {
181 value.as_cow()
182 }
183}
184
185impl<'a> From<&'a Literal> for CowTerm<'a> {
186 fn from(value: &'a Literal) -> Self {
187 Self::Ground(value.into())
188 }
189}
190
191impl<'a> From<CowLiteral<'a>> for CowTerm<'a> {
192 fn from(value: CowLiteral<'a>) -> Self {
193 Self::Ground(value.into())
194 }
195}
196
197impl<'a> From<LiteralRef<'a>> for CowTerm<'a> {
198 fn from(value: LiteralRef<'a>) -> Self {
199 Self::Ground(value.into())
200 }
201}
202
203impl<'a> From<&'a Id> for CowTerm<'a> {
204 fn from(value: &'a Id) -> Self {
205 match value {
206 Id::BlankId(b) => b.into(),
207 Id::Iri(i) => i.into(),
208 }
209 }
210}
211
212impl<'a> From<&'a BlankId> for CowTerm<'a> {
213 fn from(value: &'a BlankId) -> Self {
214 Self::BlankId(Cow::Borrowed(value))
215 }
216}
217
218impl<'a> From<&'a BlankIdBuf> for CowTerm<'a> {
219 fn from(value: &'a BlankIdBuf) -> Self {
220 Self::BlankId(Cow::Borrowed(value))
221 }
222}
223
224impl<'a> From<&'a Iri> for CowTerm<'a> {
225 fn from(value: &'a Iri) -> Self {
226 Self::Ground(value.into())
227 }
228}
229
230impl<'a> From<&'a IriBuf> for CowTerm<'a> {
231 fn from(value: &'a IriBuf) -> Self {
232 Self::Ground(value.into())
233 }
234}
235
236impl<'a> From<&'a str> for CowTerm<'a> {
237 fn from(value: &'a str) -> Self {
238 Self::Ground(value.into())
239 }
240}
241
242impl<'a> From<&'a String> for CowTerm<'a> {
243 fn from(value: &'a String) -> Self {
244 Self::Ground(value.into())
245 }
246}
247
248impl PartialEq<Iri> for CowTerm<'_> {
249 fn eq(&self, other: &Iri) -> bool {
250 match self {
251 Self::Ground(CowGroundTerm::Iri(this)) => this.as_ref() == other,
252 _ => false,
253 }
254 }
255}
256
257impl PartialEq<&Iri> for CowTerm<'_> {
258 fn eq(&self, other: &&Iri) -> bool {
259 self.eq(*other)
260 }
261}
262
263impl PartialEq<Term> for CowTerm<'_> {
264 fn eq(&self, other: &Term) -> bool {
265 self.as_ref() == *other
266 }
267}
268
269impl PartialEq<CowTerm<'_>> for Term {
270 fn eq(&self, other: &CowTerm<'_>) -> bool {
271 *self == other.as_ref()
272 }
273}
274
275impl<'a> PartialEq<TermRef<'a>> for CowTerm<'_> {
276 fn eq(&self, other: &TermRef<'a>) -> bool {
277 self.as_ref() == *other
278 }
279}
280
281impl PartialEq<CowTerm<'_>> for TermRef<'_> {
282 fn eq(&self, other: &CowTerm<'_>) -> bool {
283 *self == other.as_ref()
284 }
285}
286
287impl PartialOrd<Term> for CowTerm<'_> {
288 fn partial_cmp(&self, other: &Term) -> Option<Ordering> {
289 self.as_ref().partial_cmp(other)
290 }
291}
292
293impl PartialOrd<CowTerm<'_>> for Term {
294 fn partial_cmp(&self, other: &CowTerm<'_>) -> Option<Ordering> {
295 self.partial_cmp(&other.as_ref())
296 }
297}
298
299impl<'a> PartialOrd<TermRef<'a>> for CowTerm<'_> {
300 fn partial_cmp(&self, other: &TermRef<'a>) -> Option<Ordering> {
301 self.as_ref().partial_cmp(other)
302 }
303}
304
305impl PartialOrd<CowTerm<'_>> for TermRef<'_> {
306 fn partial_cmp(&self, other: &CowTerm<'_>) -> Option<Ordering> {
307 self.partial_cmp(&other.as_ref())
308 }
309}
310
311impl fmt::Display for CowTerm<'_> {
312 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
313 match self {
314 Self::BlankId(id) => id.fmt(f),
315 Self::Ground(g) => g.fmt(f),
316 }
317 }
318}
319
320impl RdfDisplay for CowTerm<'_> {
321 fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
322 match self {
323 Self::BlankId(id) => id.rdf_fmt(f),
324 Self::Ground(g) => g.rdf_fmt(f),
325 }
326 }
327}