1use crate::{BlankId, BlankIdBuf, Literal, LiteralRef, RdfDisplay, TripleTerm};
2use std::{borrow::Cow, fmt, hash::Hash, sync::Arc};
3
4mod r#ref;
5use iri_rs::{Iri, IriBuf};
6pub use r#ref::*;
7
8mod cow;
9pub use cow::*;
10
11use super::Term;
12
13#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
20#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
21#[cfg_attr(feature = "serde", serde(untagged))]
22pub enum LocalTerm {
23 BlankId(BlankIdBuf),
24 Named(Term),
25 Triple(Arc<TripleTerm>),
31}
32
33impl LocalTerm {
34 pub const fn iri(iri: IriBuf) -> Self {
35 Self::Named(Term::Iri(iri))
36 }
37
38 pub const fn literal(literal: Literal) -> Self {
39 Self::Named(Term::Literal(literal))
40 }
41
42 pub fn triple(t: TripleTerm) -> Self {
44 Self::Triple(Arc::new(t))
45 }
46
47 pub const fn triple_arc(t: Arc<TripleTerm>) -> Self {
51 Self::Triple(t)
52 }
53
54 pub const fn is_blank_id(&self) -> bool {
55 matches!(self, Self::BlankId(_))
56 }
57
58 pub const fn is_triple(&self) -> bool {
60 matches!(self, Self::Triple(_))
61 }
62
63 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<&str>> {
71 match self {
72 Self::Named(t) => t.as_iri(),
73 _ => None,
74 }
75 }
76
77 pub fn as_literal(&self) -> Option<LiteralRef<'_>> {
78 match self {
79 Self::Named(t) => t.as_literal(),
80 _ => None,
81 }
82 }
83
84 pub fn as_triple(&self) -> Option<&TripleTerm> {
86 match self {
87 Self::Triple(t) => Some(t),
88 _ => None,
89 }
90 }
91
92 pub fn into_triple(self) -> Option<TripleTerm> {
95 match self {
96 Self::Triple(t) => Some(Arc::try_unwrap(t).unwrap_or_else(|arc| (*arc).clone())),
97 _ => None,
98 }
99 }
100
101 pub fn try_into_triple(self) -> Result<TripleTerm, Self> {
105 match self {
106 Self::Triple(t) => Ok(Arc::try_unwrap(t).unwrap_or_else(|arc| (*arc).clone())),
107 other => Err(other),
108 }
109 }
110
111 pub fn as_ref(&self) -> LocalTermRef<'_> {
112 match self {
113 Self::BlankId(blank_id) => LocalTermRef::BlankId(blank_id),
114 Self::Named(named) => LocalTermRef::Named(named.as_ref()),
115 Self::Triple(t) => LocalTermRef::Triple(t),
116 }
117 }
118
119 pub fn as_cow(&self) -> CowLocalTerm<'_> {
120 match self {
121 Self::BlankId(blank_id) => CowLocalTerm::BlankId(Cow::Borrowed(blank_id)),
122 Self::Named(named) => CowLocalTerm::Named(named.as_cow()),
123 Self::Triple(t) => CowLocalTerm::Triple(Cow::Borrowed(t)),
124 }
125 }
126
127 pub fn into_cow(self) -> CowLocalTerm<'static> {
128 match self {
129 Self::BlankId(blank_id) => CowLocalTerm::BlankId(Cow::Owned(blank_id)),
130 Self::Named(named) => CowLocalTerm::Named(named.into_cow()),
131 Self::Triple(t) => CowLocalTerm::Triple(Cow::Owned(Arc::try_unwrap(t).unwrap_or_else(|arc| (*arc).clone()))),
132 }
133 }
134}
135
136impl From<IriBuf> for LocalTerm {
137 fn from(value: IriBuf) -> Self {
138 Self::iri(value)
139 }
140}
141
142impl From<Literal> for LocalTerm {
143 fn from(value: Literal) -> Self {
144 Self::literal(value)
145 }
146}
147
148impl From<Term> for LocalTerm {
149 fn from(value: Term) -> Self {
150 Self::Named(value)
151 }
152}
153
154impl From<BlankIdBuf> for LocalTerm {
155 fn from(value: BlankIdBuf) -> Self {
156 Self::BlankId(value)
157 }
158}
159
160impl From<TripleTerm> for LocalTerm {
161 fn from(value: TripleTerm) -> Self {
162 Self::triple(value)
163 }
164}
165
166impl Hash for LocalTerm {
167 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
168 match self {
169 Self::BlankId(id) => {
170 state.write_u8(0);
171 id.hash(state);
172 }
173 Self::Named(l) => {
174 state.write_u8(1);
175 l.hash(state);
176 }
177 Self::Triple(t) => {
178 state.write_u8(2);
179 t.hash(state);
180 }
181 }
182 }
183}
184
185impl fmt::Display for LocalTerm {
186 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
187 match self {
188 Self::BlankId(id) => id.fmt(f),
189 Self::Named(lit) => lit.fmt(f),
190 Self::Triple(t) => write_triple_term(f, t),
191 }
192 }
193}
194
195impl RdfDisplay for LocalTerm {
196 fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
197 match self {
198 Self::BlankId(id) => id.rdf_fmt(f),
199 Self::Named(lit) => lit.rdf_fmt(f),
200 Self::Triple(t) => write_triple_term(f, t),
201 }
202 }
203}
204
205fn write_triple_term(f: &mut fmt::Formatter, t: &TripleTerm) -> fmt::Result {
206 f.write_str("<<( ")?;
207 t.rdf_fmt(f)?;
208 f.write_str(" )>>")
209}