1use crate::{Id, ValidId};
2use contextual::{AsRefWithContext, DisplayWithContext, WithContext};
3use iref::IriBuf;
4use json_ld_syntax::Keyword;
5use rdf_types::{vocabulary::Vocabulary, BlankIdBuf};
6use std::fmt;
7
8#[derive(Clone, PartialEq, Eq, Hash)]
10pub enum Term<T = IriBuf, B = BlankIdBuf> {
11 Null,
13
14 Id(Id<T, B>),
16
17 Keyword(Keyword),
19}
20
21impl<I, B> Term<I, B> {
22 pub fn is_null(&self) -> bool {
24 matches!(self, Term::Null)
25 }
26
27 pub fn into_iri(self) -> Result<I, Self> {
31 match self {
32 Term::Id(Id::Valid(ValidId::Iri(id))) => Ok(id),
33 term => Err(term),
34 }
35 }
36
37 pub fn is_keyword(&self) -> bool {
39 matches!(self, Term::Keyword(_))
40 }
41
42 pub fn as_iri(&self) -> Option<&I> {
44 match self {
45 Term::Id(p) => p.as_iri(),
46 _ => None,
47 }
48 }
49
50 pub fn map_id<U, C>(
51 self,
52 f: impl FnOnce(rdf_types::Id<I, B>) -> rdf_types::Id<U, C>,
53 ) -> Term<U, C> {
54 match self {
55 Self::Null => Term::Null,
56 Self::Keyword(k) => Term::Keyword(k),
57 Self::Id(id) => Term::Id(id.map(f)),
58 }
59 }
60}
61
62impl<T, B, N: Vocabulary<Iri = T, BlankId = B>> DisplayWithContext<N> for Term<T, B> {
63 fn fmt_with(&self, vocabulary: &N, f: &mut fmt::Formatter) -> fmt::Result {
64 use std::fmt::Display;
65 match self {
66 Self::Null => write!(f, "null"),
67 Self::Id(id) => id.with(vocabulary).fmt(f),
68 Self::Keyword(k) => k.fmt(f),
69 }
70 }
71}
72
73impl<T: AsRef<str>, B: AsRef<str>> Term<T, B> {
74 pub fn as_str(&self) -> &str {
75 match self {
76 Term::Id(p) => p.as_str(),
77 Term::Keyword(k) => k.into_str(),
78 Term::Null => "",
79 }
80 }
81}
82
83impl<T, B, N: Vocabulary<Iri = T, BlankId = B>> AsRefWithContext<str, N> for Term<T, B> {
84 fn as_ref_with<'a>(&'a self, vocabulary: &'a N) -> &'a str {
85 match self {
86 Term::Id(p) => p.with(vocabulary).as_str(),
87 Term::Keyword(k) => k.into_str(),
88 Term::Null => "",
89 }
90 }
91}
92
93impl<'a, T, B> From<&'a Term<T, B>> for Term<&'a T, &'a B> {
94 fn from(t: &'a Term<T, B>) -> Term<&'a T, &'a B> {
95 match t {
96 Term::Null => Term::Null,
97 Term::Id(r) => Term::Id(r.into()),
98 Term::Keyword(k) => Term::Keyword(*k),
99 }
100 }
101}
102
103impl<T, B> From<T> for Term<T, B> {
104 fn from(id: T) -> Term<T, B> {
105 Term::Id(Id::Valid(ValidId::Iri(id)))
106 }
107}
108
109impl<T, B> From<Id<T, B>> for Term<T, B> {
110 fn from(prop: Id<T, B>) -> Term<T, B> {
111 Term::Id(prop)
112 }
113}
114
115impl<T: fmt::Display, B: fmt::Display> fmt::Display for Term<T, B> {
116 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
117 match self {
118 Term::Id(p) => p.fmt(f),
119 Term::Keyword(kw) => kw.fmt(f),
120 Term::Null => write!(f, "null"),
121 }
122 }
123}
124
125impl<T: fmt::Debug, B: fmt::Debug> fmt::Debug for Term<T, B> {
126 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
127 match self {
128 Term::Id(p) => write!(f, "Term::Ref({p:?})"),
129 Term::Keyword(kw) => write!(f, "Term::Keyword({kw})"),
130 Term::Null => write!(f, "Term::Null"),
131 }
132 }
133}