1use super::*;
2use crate::term::{Term, TermKind};
3
4#[derive(Clone, Copy, Debug)]
12pub struct NsTerm<'a> {
13 pub(crate) ns: IriRef<&'a str>,
14 pub(crate) suffix: &'a str,
16}
17
18impl fmt::Display for NsTerm<'_> {
19 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
20 write!(f, "{}{}", self.ns.as_str(), self.suffix)
21 }
22}
23
24impl<'a> NsTerm<'a> {
25 pub const fn new_unchecked(ns: IriRef<&'a str>, suffix: &'a str) -> Self {
27 NsTerm { ns, suffix }
28 }
29
30 pub fn iriref(&self) -> IriRef<MownStr> {
32 IriRef::new_unchecked(if self.suffix.is_empty() {
33 self.ns.as_str().into()
34 } else {
35 self.to_string().into()
36 })
37 }
38
39 pub fn to_iriref(self) -> IriRef<MownStr<'a>> {
41 if self.suffix.is_empty() {
42 self.ns.map_unchecked(MownStr::from)
43 } else {
44 IriRef::new_unchecked(self.to_string().into())
45 }
46 }
47}
48
49impl<'a> Term for NsTerm<'a> {
50 type BorrowTerm<'x> = &'x Self where 'a: 'x;
51
52 fn kind(&self) -> TermKind {
53 TermKind::Iri
54 }
55 fn iri(&self) -> Option<IriRef<MownStr<'_>>> {
56 Some(self.iriref())
57 }
58 fn borrow_term(&self) -> Self::BorrowTerm<'_> {
59 self
60 }
61 fn eq<T: Term>(&self, other: T) -> bool {
62 match other.iri() {
63 Some(iri) => {
64 let ns = self.ns.as_str();
65 iri.as_str().starts_with(ns) && &iri[ns.len()..] == self.suffix
66 }
67 None => false,
68 }
69 }
70}
71
72impl<'a, T: Term> PartialEq<T> for NsTerm<'a> {
73 fn eq(&self, other: &T) -> bool {
74 Term::eq(self, other.borrow_term())
75 }
76}
77
78impl<'a> Eq for NsTerm<'a> {}
79
80#[cfg(test)]
81mod test {
82 use super::*;
83
84 #[test]
85 fn ns_term_eq() {
86 let ns = IriRef::new_unchecked("http://example.org/");
87 let t1a = NsTerm { ns, suffix: "foo" };
88 let t2a = NsTerm {
89 ns,
90 suffix: "foo/bar",
91 };
92 let t3a = NsTerm { ns, suffix: "bar" };
93 let t1b = IriRef::new_unchecked("http://example.org/foo");
94 let t2b = IriRef::new_unchecked("http://example.org/foo/bar");
95 let t3b = IriRef::new_unchecked("http://example.org/bar");
96
97 assert!(t1a == t1b);
98 assert!(t2a == t2b);
99 assert!(t3a == t3b);
100 assert!(t1a != t2b);
101 assert!(t2a != t3b);
102 assert!(t3a != t1b);
103 }
104}
105
106impl<'a> std::ops::Mul<NsTerm<'a>> for &'a str {
107 type Output = crate::term::SimpleTerm<'a>;
108
109 fn mul(self, rhs: NsTerm<'a>) -> Self::Output {
110 crate::term::SimpleTerm::LiteralDatatype(self.into(), rhs.to_iriref())
111 }
112}