1use core::fmt;
2use std::borrow::Cow;
3use std::cmp::Ordering;
4
5use into_owned_trait::IntoOwned;
6use iref::Iri;
7
8use crate::{BlankId, IdRef, LiteralRef, RdfDisplay};
9
10use super::{CowTerm, GroundTermRef, Term};
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
14pub enum TermRef<'a> {
15 BlankId(&'a BlankId),
17
18 Ground(GroundTermRef<'a>),
20}
21
22impl<'a> TermRef<'a> {
23 pub fn is_id(&self) -> bool {
26 matches!(self, Self::BlankId(_) | Self::Ground(GroundTermRef::Iri(_)))
27 }
28
29 pub fn as_id(&self) -> Option<IdRef<'a>> {
31 match self {
32 Self::BlankId(b) => Some(IdRef::BlankId(b)),
33 Self::Ground(GroundTermRef::Iri(iri)) => Some(IdRef::Iri(iri)),
34 _ => None,
35 }
36 }
37
38 pub fn into_id(self) -> Result<IdRef<'a>, LiteralRef<'a>> {
41 match self {
42 Self::BlankId(b) => Ok(IdRef::BlankId(b)),
43 Self::Ground(GroundTermRef::Iri(iri)) => Ok(IdRef::Iri(iri)),
44 Self::Ground(GroundTermRef::Literal(lit)) => Err(lit),
45 }
46 }
47
48 pub fn is_blank_id(&self) -> bool {
50 matches!(self, Self::BlankId(_))
51 }
52
53 pub fn is_ground(&self) -> bool {
56 matches!(self, Self::Ground(_))
57 }
58
59 pub fn is_iri(&self) -> bool {
61 matches!(self, Self::Ground(GroundTermRef::Iri(_)))
62 }
63
64 pub fn is_literal(&self) -> bool {
66 matches!(self, Self::Ground(GroundTermRef::Literal(_)))
67 }
68
69 pub fn as_blank_id(&self) -> Option<&'a BlankId> {
71 match self {
72 Self::BlankId(b) => Some(b),
73 _ => None,
74 }
75 }
76
77 pub fn as_ground(&self) -> Option<GroundTermRef<'a>> {
79 match self {
80 Self::Ground(g) => Some(*g),
81 _ => None,
82 }
83 }
84
85 pub fn as_iri(&self) -> Option<&'a Iri> {
87 match self {
88 Self::Ground(g) => g.as_iri(),
89 _ => None,
90 }
91 }
92
93 pub fn as_literal(&self) -> Option<LiteralRef<'a>> {
95 match self {
96 Self::Ground(g) => g.as_literal(),
97 _ => None,
98 }
99 }
100
101 pub fn into_ground(self) -> Result<GroundTermRef<'a>, &'a BlankId> {
104 match self {
105 Self::Ground(g) => Ok(g),
106 Self::BlankId(b) => Err(b),
107 }
108 }
109
110 pub fn into_cow(self) -> CowTerm<'a> {
112 match self {
113 Self::BlankId(b) => CowTerm::BlankId(Cow::Borrowed(b)),
114 Self::Ground(g) => CowTerm::Ground(g.into_cow()),
115 }
116 }
117}
118
119impl TermRef<'_> {
120 pub fn to_owned(&self) -> Term {
122 (*self).into_owned()
123 }
124}
125
126impl IntoOwned for TermRef<'_> {
127 type Owned = Term;
128
129 fn into_owned(self) -> Term {
130 match self {
131 Self::BlankId(blank_id) => Term::BlankId(blank_id.to_owned()),
132 Self::Ground(named) => Term::Ground(named.to_owned()),
133 }
134 }
135}
136
137impl equivalent::Equivalent<Term> for TermRef<'_> {
138 fn equivalent(&self, key: &Term) -> bool {
139 self == key
140 }
141}
142
143impl equivalent::Comparable<Term> for TermRef<'_> {
144 fn compare(&self, key: &Term) -> std::cmp::Ordering {
145 self.partial_cmp(key).unwrap()
146 }
147}
148
149impl From<TermRef<'_>> for Term {
150 fn from(value: TermRef<'_>) -> Self {
151 value.to_owned()
152 }
153}
154
155impl PartialEq<Term> for TermRef<'_> {
156 fn eq(&self, other: &Term) -> bool {
157 match (self, other) {
158 (Self::BlankId(a), Term::BlankId(b)) => *a == b,
159 (Self::Ground(a), Term::Ground(b)) => a == b,
160 _ => false,
161 }
162 }
163}
164
165impl PartialOrd<Term> for TermRef<'_> {
166 fn partial_cmp(&self, other: &Term) -> Option<Ordering> {
167 match (self, other) {
168 (Self::BlankId(a), Term::BlankId(b)) => (*a).partial_cmp(b),
169 (Self::BlankId(_), Term::Ground(_)) => Some(Ordering::Less),
170 (Self::Ground(_), Term::BlankId(_)) => Some(Ordering::Greater),
171 (Self::Ground(a), Term::Ground(b)) => (*a).partial_cmp(b),
172 }
173 }
174}
175
176impl fmt::Display for TermRef<'_> {
177 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
178 match self {
179 Self::BlankId(id) => id.fmt(f),
180 Self::Ground(g) => g.fmt(f),
181 }
182 }
183}
184
185impl RdfDisplay for TermRef<'_> {
186 fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
187 match self {
188 Self::BlankId(id) => id.rdf_fmt(f),
189 Self::Ground(g) => g.rdf_fmt(f),
190 }
191 }
192}