1use super::*;
2use crate::ns::rdf;
3
4lazy_static::lazy_static! {
5 static ref RDF_LANG_STRING: Box<str> = rdf::langString.iri().unwrap().unwrap().into();
6}
7
8#[derive(Clone, Debug)]
10pub enum SimpleTerm<'a> {
11 Iri(IriRef<MownStr<'a>>),
13 BlankNode(BnodeId<MownStr<'a>>),
15 LiteralDatatype(MownStr<'a>, IriRef<MownStr<'a>>),
17 LiteralLanguage(MownStr<'a>, LanguageTag<MownStr<'a>>),
19 Triple(Box<[Self; 3]>),
21 Variable(VarName<MownStr<'a>>),
23}
24
25use SimpleTerm::*;
26
27impl<'a> Term for SimpleTerm<'a> {
28 type BorrowTerm<'x> = &'x Self where 'a: 'x;
29
30 fn kind(&self) -> TermKind {
31 match self {
32 Iri(_) => TermKind::Iri,
33 BlankNode(_) => TermKind::BlankNode,
34 LiteralDatatype(..) | LiteralLanguage(..) => TermKind::Literal,
35 Triple(_) => TermKind::Triple,
36 Variable(_) => TermKind::Variable,
37 }
38 }
39 fn iri(&self) -> Option<IriRef<MownStr>> {
40 if let Iri(iri) = self {
41 Some(IriRef::new_unchecked(iri.borrowed()))
42 } else {
43 None
44 }
45 }
46 fn bnode_id(&self) -> Option<BnodeId<MownStr>> {
47 if let BlankNode(bnid) = self {
48 Some(BnodeId::new_unchecked(bnid.borrowed()))
49 } else {
50 None
51 }
52 }
53 fn lexical_form(&self) -> Option<MownStr> {
54 match self {
55 LiteralDatatype(val, _) | LiteralLanguage(val, _) => Some(MownStr::from(&val[..])),
56 _ => None,
57 }
58 }
59 fn datatype(&self) -> Option<IriRef<MownStr>> {
60 match self {
61 LiteralDatatype(_, iri) => Some(IriRef::new_unchecked(iri.borrowed())),
62 LiteralLanguage(..) => Some(IriRef::new_unchecked(MownStr::from_str(&RDF_LANG_STRING))),
63 _ => None,
64 }
65 }
66 fn language_tag(&self) -> Option<LanguageTag<MownStr>> {
67 if let LiteralLanguage(_, tag) = self {
68 Some(LanguageTag::new_unchecked(MownStr::from_str(tag)))
69 } else {
70 None
71 }
72 }
73 fn variable(&self) -> Option<VarName<MownStr>> {
74 if let Variable(name) = self {
75 Some(VarName::new_unchecked(MownStr::from_str(name)))
76 } else {
77 None
78 }
79 }
80 fn triple(&self) -> Option<[Self::BorrowTerm<'_>; 3]> {
81 if let Triple(triple) = self {
82 let [s, p, o] = triple.as_ref();
83 Some([s, p, o])
84 } else {
85 None
86 }
87 }
88 fn to_triple(self) -> Option<[Self; 3]> {
89 if let Triple(triple) = self {
90 Some(*triple)
91 } else {
92 None
93 }
94 }
95 fn borrow_term(&self) -> Self::BorrowTerm<'_> {
96 self
97 }
98}
99
100fn ensure_owned(m: MownStr) -> MownStr<'static> {
101 if m.is_owned() {
102 let m = m.clone();
103 unsafe { std::mem::transmute(m) }
106 } else {
107 m.to_string().into()
108 }
109}
110
111impl FromTerm for SimpleTerm<'static> {
112 fn from_term<T: Term>(term: T) -> Self {
113 match term.kind() {
114 TermKind::Iri => SimpleTerm::Iri(term.iri().unwrap().map_unchecked(ensure_owned)),
115 TermKind::BlankNode => {
116 SimpleTerm::BlankNode(term.bnode_id().unwrap().map_unchecked(ensure_owned))
117 }
118 TermKind::Literal => {
119 let lex = ensure_owned(term.lexical_form().unwrap());
120 if let Some(tag) = term.language_tag() {
121 let tag = tag.map_unchecked(ensure_owned);
122 SimpleTerm::LiteralLanguage(lex, tag)
123 } else {
124 let dt = term.datatype().unwrap().map_unchecked(ensure_owned);
125 SimpleTerm::LiteralDatatype(lex, dt)
126 }
127 }
128 TermKind::Triple => {
129 let t = term.triple().unwrap();
130 SimpleTerm::Triple(Box::new([
131 Self::from_term(t.s()),
132 Self::from_term(t.p()),
133 Self::from_term(t.o()),
134 ]))
135 }
136 TermKind::Variable => {
137 SimpleTerm::Variable(term.variable().unwrap().map_unchecked(ensure_owned))
138 }
139 }
140 }
141}
142
143impl TryFromTerm for SimpleTerm<'static> {
144 type Error = std::convert::Infallible;
145
146 fn try_from_term<T: Term>(term: T) -> Result<Self, Self::Error> {
147 Ok(Self::from_term(term))
148 }
149}
150
151impl<'a> SimpleTerm<'a> {
152 pub fn from_term_ref<T>(term: &'a T) -> Self
157 where
158 T: Term + ?Sized,
159 {
160 match term.kind() {
161 TermKind::Iri => SimpleTerm::Iri(term.iri().unwrap()),
162 TermKind::BlankNode => SimpleTerm::BlankNode(term.bnode_id().unwrap()),
163 TermKind::Literal => {
164 let lex = term.lexical_form().unwrap();
165 if let Some(tag) = term.language_tag() {
166 SimpleTerm::LiteralLanguage(lex, tag)
167 } else {
168 let dt = term.datatype().unwrap();
169 SimpleTerm::LiteralDatatype(lex, dt)
170 }
171 }
172 TermKind::Triple => {
173 let t = term.triple().unwrap();
174 SimpleTerm::Triple(Box::new([
175 SimpleTerm::<'static>::from_term(t.s()),
176 SimpleTerm::<'static>::from_term(t.p()),
177 SimpleTerm::<'static>::from_term(t.o()),
178 ]))
179 }
180 TermKind::Variable => SimpleTerm::Variable(term.variable().unwrap()),
181 }
182 }
183
184 pub fn from_triple<T: crate::triple::Triple>(triple: T) -> Self {
186 Self::Triple(Box::new([
187 triple.s().into_term(),
188 triple.p().into_term(),
189 triple.o().into_term(),
190 ]))
191 }
192}
193
194impl<T: Term> PartialEq<T> for SimpleTerm<'_> {
195 fn eq(&self, other: &T) -> bool {
196 Term::eq(self, other.borrow_term())
197 }
198}
199
200impl Eq for SimpleTerm<'_> {}
201
202impl std::hash::Hash for SimpleTerm<'_> {
203 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
204 Term::hash(self, state)
205 }
206}
207
208impl<T: Term> PartialOrd<T> for SimpleTerm<'_> {
209 fn partial_cmp(&self, other: &T) -> Option<Ordering> {
210 Some(Term::cmp(self, other.borrow_term()))
211 }
212}
213
214impl Ord for SimpleTerm<'_> {
215 fn cmp(&self, other: &Self) -> Ordering {
216 Term::cmp(self, other)
217 }
218}
219
220#[cfg(test)]
221mod test {
222 use super::*;
223 use crate::ns::xsd;
224
225 #[test]
226 fn iri_from_scratch() {
227 let value = IriRef::new_unchecked(MownStr::from_str("http://example.org/"));
228 let t = SimpleTerm::Iri(value.clone());
229 assert_consistent_term_impl(&t);
230 assert_eq!(t.borrow_term(), &t);
231 assert_eq!(t.kind(), TermKind::Iri);
232 assert_eq!(t.iri(), Some(value));
233 }
234
235 #[test]
236 fn bnode_from_scratch() {
237 let value = BnodeId::new_unchecked(MownStr::from_str("b1"));
238 let t = SimpleTerm::BlankNode(value.clone());
239 assert_consistent_term_impl(&t);
240 assert_eq!(t.borrow_term(), &t);
241 assert_eq!(t.kind(), TermKind::BlankNode);
242 assert_eq!(t.bnode_id(), Some(value));
243 }
244
245 #[test]
246 fn literal_dt_from_scratch() {
247 let value = MownStr::from_str("hello world");
248 let datatype = IriRef::new_unchecked(MownStr::from_str("http://example.org/"));
249 let t = SimpleTerm::LiteralDatatype(value.clone(), datatype.clone());
250 assert_consistent_term_impl(&t);
251 assert_eq!(t.borrow_term(), &t);
252 assert_eq!(t.kind(), TermKind::Literal);
253 assert_eq!(t.lexical_form(), Some(value));
254 assert_eq!(t.datatype(), Some(datatype));
255 }
256
257 #[test]
258 fn literal_lang_from_scratch() {
259 let value = MownStr::from_str("hello world");
260 let tag = LanguageTag::new_unchecked(MownStr::from_str("en-US"));
261 let t = SimpleTerm::LiteralLanguage(value.clone(), tag.clone());
262 assert_consistent_term_impl(&t);
263 assert_eq!(t.borrow_term(), &t);
264 assert_eq!(t.kind(), TermKind::Literal);
265 assert_eq!(t.lexical_form(), Some(value));
266 assert_eq!(t.language_tag(), Some(tag));
267 }
268
269 #[test]
270 fn variable_from_scratch() {
271 let value = VarName::new_unchecked(MownStr::from_str("x"));
272 let t = SimpleTerm::Variable(value.clone());
273 assert_consistent_term_impl(&t);
274 assert_eq!(t.borrow_term(), &t);
275 assert_eq!(t.kind(), TermKind::Variable);
276 assert_eq!(t.variable(), Some(value));
277 }
278
279 #[test]
280 fn triple_from_scratch() {
281 let s: SimpleTerm<'_> = BnodeId::new_unchecked(MownStr::from_str("s")).into_term();
282 let p: SimpleTerm<'_> = IriRef::new_unchecked(MownStr::from_str("p")).into_term();
283 let o: SimpleTerm<'_> = "o".into_term();
284 let spo = [s.clone(), p.clone(), o.clone()];
285 let t = SimpleTerm::Triple(Box::new(spo.clone()));
286 assert_consistent_term_impl(&t);
287 assert_eq!(t.borrow_term(), &t);
288 assert_eq!(t.kind(), TermKind::Triple);
289 assert_eq!(t.triple(), Some([&s, &p, &o]));
290 assert_eq!(t.clone().to_triple(), Some(spo.clone()));
291 assert_eq!(t.constituents().collect::<Vec<_>>(), vec![&t, &s, &p, &o]);
292 assert_eq!(
293 t.clone().to_constituents().collect::<Vec<_>>(),
294 t.constituents().cloned().collect::<Vec<_>>()
295 );
296 assert_eq!(t.atoms().collect::<Vec<_>>(), vec![&s, &p, &o]);
297 assert_eq!(
298 t.clone().to_atoms().collect::<Vec<_>>(),
299 Vec::from(spo.clone())
300 );
301 }
302
303 #[test]
304 fn nested_triple_from_scratch() {
305 let s1: SimpleTerm<'_> = BnodeId::new_unchecked(MownStr::from_str("s")).into_term();
306 let p1: SimpleTerm<'_> = IriRef::new_unchecked(MownStr::from_str("p")).into_term();
307 let o1: SimpleTerm<'_> = "o".into_term();
308 let spo1 = [s1.clone(), p1.clone(), o1.clone()];
309 let t1 = SimpleTerm::Triple(Box::new(spo1));
310 let s: SimpleTerm<'_> = s1.clone();
311 let p: SimpleTerm<'_> = p1.clone();
312 let o = t1.clone();
313 let spo2 = [s.clone(), p.clone(), o.clone()];
314 let t = SimpleTerm::Triple(Box::new(spo2.clone()));
315 assert_consistent_term_impl(&t);
316 assert_eq!(t.borrow_term(), &t);
317 assert_eq!(t.kind(), TermKind::Triple);
318 assert_eq!(t.triple(), Some([&s, &p, &o]));
319 assert_eq!(t.clone().to_triple(), Some(spo2.clone()));
320 assert_eq!(
321 t.constituents().collect::<Vec<_>>(),
322 vec![&t, &s, &p, &t1, &s1, &p1, &o1]
323 );
324 assert_eq!(
325 t.clone().to_constituents().collect::<Vec<_>>(),
326 t.constituents().cloned().collect::<Vec<_>>()
327 );
328 assert_eq!(t.atoms().collect::<Vec<_>>(), vec![&s, &p, &s1, &p1, &o1]);
329 assert_eq!(
330 t.clone().to_atoms().collect::<Vec<_>>(),
331 t.atoms().cloned().collect::<Vec<_>>()
332 );
333 }
334
335 #[test]
336 fn iri_from_term() {
337 let t: SimpleTerm<'_> = rdf::type_.into_term();
338 assert_consistent_term_impl(&t);
339 assert_eq!(t.kind(), TermKind::Iri);
340 assert_eq!(t.iri(), rdf::type_.iri());
341 }
342
343 #[test]
344 fn literal_from_term() {
345 let t: SimpleTerm<'_> = "hello world".into_term();
346 assert_consistent_term_impl(&t);
347 assert_eq!(t.kind(), TermKind::Literal);
348 assert_eq!(t.lexical_form().unwrap(), "hello world");
349 assert_eq!(t.datatype(), xsd::string.iri());
350
351 let t: SimpleTerm<'_> = 42.into_term();
352 assert_consistent_term_impl(&t);
353 assert_eq!(t.kind(), TermKind::Literal);
354 assert_eq!(t.lexical_form().unwrap(), "42");
355 assert_eq!(t.datatype(), xsd::integer.iri());
356 }
357
358 #[test]
359 fn bnode_from_term() {
360 let b1 = BnodeId::new("b1").unwrap();
361 let t: SimpleTerm<'_> = b1.into_term();
362 assert_consistent_term_impl(&t);
363 assert_eq!(t.kind(), TermKind::BlankNode);
364 assert_eq!(t.bnode_id().unwrap(), b1);
365 }
366
367 #[test]
368 fn triple_from_term() {
369 let s: SimpleTerm<'_> = BnodeId::new_unchecked(MownStr::from_str("s")).into_term();
370 let p: SimpleTerm<'_> = IriRef::new_unchecked(MownStr::from_str("p")).into_term();
371 let o: SimpleTerm<'_> = "o".into_term();
372 let spo = [s.clone(), p.clone(), o.clone()];
373 let tr = SimpleTerm::from_triple(spo.spo());
374 let t: SimpleTerm<'_> = tr.into_term();
375 assert_consistent_term_impl(&t);
376 assert_eq!(t.borrow_term(), &t);
377 assert_eq!(t.kind(), TermKind::Triple);
378 assert_eq!(t.triple(), Some([&s, &p, &o]));
379 assert_eq!(t.clone().to_triple(), Some(spo.clone()));
380 assert_eq!(t.constituents().collect::<Vec<_>>(), vec![&t, &s, &p, &o]);
381 assert_eq!(
382 t.clone().to_constituents().collect::<Vec<_>>(),
383 t.constituents().cloned().collect::<Vec<_>>()
384 );
385 assert_eq!(t.atoms().collect::<Vec<_>>(), vec![&s, &p, &o]);
386 assert_eq!(
387 t.clone().to_atoms().collect::<Vec<_>>(),
388 Vec::from(spo.clone())
389 );
390 }
391
392 #[test]
393 fn variable_from_term() {
394 let v1 = VarName::new("v1").unwrap();
395 let t: SimpleTerm<'_> = v1.into_term();
396 assert_consistent_term_impl(&t);
397 assert_eq!(t.kind(), TermKind::Variable);
398 assert_eq!(t.variable().unwrap(), v1);
399 }
400
401 #[test]
402 fn try_from_term() {
403 let t: SimpleTerm<'_> = 42.try_into_term().unwrap();
404 assert_consistent_term_impl(&t);
405 assert_eq!(t.kind(), TermKind::Literal);
406 assert_eq!(t.lexical_form().unwrap(), "42");
407 assert_eq!(t.datatype(), xsd::integer.iri());
408 }
409
410 #[test]
411 fn iri_from_term_ref() {
412 let i = sophia_iri::Iri::new("http://example.com/").unwrap();
413 let t = SimpleTerm::from_term_ref(&i);
414 assert_consistent_term_impl(&t);
415 assert_eq!(t.kind(), TermKind::Iri);
416 assert_eq!(t.iri(), i.iri());
417 assert!(t.iri().unwrap().unwrap().is_borrowed());
418 }
419
420 #[test]
421 fn literal_from_term_ref() {
422 let l = "hello world";
423 let t = SimpleTerm::from_term_ref(&l);
424 assert_consistent_term_impl(&t);
425 assert_eq!(t.kind(), TermKind::Literal);
426 assert_eq!(t.lexical_form().unwrap(), l);
427 assert!(t.lexical_form().unwrap().is_borrowed());
428 }
429
430 #[test]
431 fn bnode_from_term_ref() {
432 let b = BnodeId::new("b1").unwrap();
433 let t = SimpleTerm::from_term_ref(&b);
434 assert_consistent_term_impl(&t);
435 assert_eq!(t.kind(), TermKind::BlankNode);
436 assert_eq!(t.bnode_id().unwrap(), b);
437 assert!(t.bnode_id().unwrap().unwrap().is_borrowed());
438 }
439
440 #[test]
441 fn triple_from_term_ref() {
442 let s: SimpleTerm<'_> = BnodeId::new_unchecked(MownStr::from_str("s")).into_term();
443 let p: SimpleTerm<'_> = IriRef::new_unchecked(MownStr::from_str("p")).into_term();
444 let o: SimpleTerm<'_> = "o".into_term();
445 let spo = [s.clone(), p.clone(), o.clone()];
446 let tr = SimpleTerm::from_triple(spo.spo());
447 let t = SimpleTerm::from_term_ref(&tr);
448 assert_consistent_term_impl(&t);
449 assert_eq!(t.kind(), TermKind::Triple);
450 let inner_s = t.to_atoms().next().unwrap();
451 assert!(inner_s.bnode_id().unwrap().unwrap().is_borrowed());
452 }
453
454 #[test]
455 fn variable_from_term_ref() {
456 let v = VarName::new("v1").unwrap();
457 let t = SimpleTerm::from_term_ref(&v);
458 assert_consistent_term_impl(&t);
459 assert_eq!(t.kind(), TermKind::Variable);
460 assert_eq!(t.variable().unwrap(), v);
461 assert!(t.variable().unwrap().unwrap().is_borrowed());
462 }
463}