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#[cfg(feature = "contextual")]
23use contextual::{AsRefWithContext, DisplayWithContext};
24
25#[derive(Clone, Copy, Eq, Ord, Debug)]
35#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
36pub enum Term<I = Id, L = Literal> {
37 Id(I),
39
40 Literal(L),
42}
43
44pub 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 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 #[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
440pub type Subject<I = IriBuf, B = BlankIdBuf> = Id<I, B>;
442
443pub type LexicalSubjectRef<'a> = LexicalIdRef<'a>;
445
446pub type Object<I = Id, L = Literal> = Term<I, L>;
448
449pub type LexicalObjectRef<'a> = LexicalTermRef<'a>;
451
452pub type GraphLabel<I = IriBuf, B = BlankIdBuf> = Id<I, B>;
454
455pub type LexicalGraphLabelRef<'a> = LexicalIdRef<'a>;
457
458pub trait AsRdfTerm<I, B, L> {
460 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}