Skip to main content

rdf_model/
triple.rs

1// This is free and unencumbered software released into the public domain.
2
3use crate::{
4    CowTerm, HeapTerm, Quad, QuadPattern, Statement, StatementPattern, Term, TriplePattern,
5};
6
7pub type TripleSlot = crate::StatementSlot;
8
9/// A triple statement.
10#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
11#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
12pub struct Triple<T: Term> {
13    pub(crate) s: T,
14    pub(crate) p: T,
15    pub(crate) o: T,
16}
17
18impl<T: Term> Triple<T> {
19    pub const fn new(s: T, p: T, o: T) -> Self {
20        Self { s, p, o }
21    }
22
23    pub fn with_subject(self, s: impl Into<T>) -> Self {
24        Self {
25            s: s.into(),
26            ..self
27        }
28    }
29
30    pub fn with_predicate(self, p: impl Into<T>) -> Self {
31        Self {
32            p: p.into(),
33            ..self
34        }
35    }
36
37    pub fn with_object(self, o: impl Into<T>) -> Self {
38        Self {
39            o: o.into(),
40            ..self
41        }
42    }
43
44    pub fn with_context(self, g: impl Into<Option<T>>) -> Quad<T> {
45        Quad::new(self.s, self.p, self.o, g.into())
46    }
47
48    pub fn into_inner(self) -> (T, T, T) {
49        (self.s, self.p, self.o)
50    }
51
52    /// Whether the statement has a constant subject.
53    pub fn has_subject(&self) -> bool {
54        true
55    }
56
57    /// Whether the statement has a constant predicate.
58    pub fn has_predicate(&self) -> bool {
59        true
60    }
61
62    /// Whether the statement has a constant object.
63    pub fn has_object(&self) -> bool {
64        true
65    }
66
67    /// Whether the statement has a constant context (graph).
68    pub fn has_context(&self) -> bool {
69        false
70    }
71
72    pub fn subject(&self) -> &T {
73        &self.s
74    }
75
76    pub fn predicate(&self) -> &T {
77        &self.p
78    }
79
80    pub fn object(&self) -> &T {
81        &self.o
82    }
83
84    pub fn context(&self) -> Option<&T> {
85        None
86    }
87}
88
89impl<T: Term + Clone> Statement for Triple<T> {
90    type Term = T;
91
92    fn subject(&self) -> &Self::Term {
93        &self.s
94    }
95
96    fn predicate(&self) -> &Self::Term {
97        &self.p
98    }
99
100    fn object(&self) -> &Self::Term {
101        &self.o
102    }
103}
104
105impl<T: Term + Clone> StatementPattern for Triple<T> {
106    type Term = T;
107
108    fn subject(&self) -> Option<&Self::Term> {
109        Some(&self.s)
110    }
111
112    fn predicate(&self) -> Option<&Self::Term> {
113        Some(&self.p)
114    }
115
116    fn object(&self) -> Option<&Self::Term> {
117        Some(&self.o)
118    }
119}
120
121impl<T: Term + Clone> Triple<T> {
122    pub fn to_triple_pattern(&self) -> TriplePattern<T> {
123        TriplePattern::new(
124            Some(self.s.clone()),
125            Some(self.p.clone()),
126            Some(self.o.clone()),
127        )
128    }
129
130    pub fn to_quad(&self) -> Quad<T> {
131        Quad::new(self.s.clone(), self.p.clone(), self.o.clone(), None)
132    }
133
134    pub fn to_quad_pattern(&self) -> QuadPattern<T> {
135        QuadPattern::new(
136            Some(self.s.clone()),
137            Some(self.p.clone()),
138            Some(self.o.clone()),
139            None,
140        )
141    }
142}
143
144impl From<Triple<CowTerm<'_>>> for Triple<HeapTerm> {
145    fn from(input: Triple<CowTerm<'_>>) -> Self {
146        Self::new(input.s.into(), input.p.into(), input.o.into())
147    }
148}
149
150impl<'a> From<&'a Triple<CowTerm<'a>>> for Triple<HeapTerm> {
151    fn from(input: &'a Triple<CowTerm<'a>>) -> Self {
152        Self::new((&input.s).into(), (&input.p).into(), (&input.o).into())
153    }
154}
155
156impl From<Quad<CowTerm<'_>>> for Triple<HeapTerm> {
157    fn from(input: Quad<CowTerm<'_>>) -> Self {
158        Self::new(input.s.into(), input.p.into(), input.o.into())
159    }
160}
161
162impl<'a> From<&'a Quad<CowTerm<'a>>> for Triple<HeapTerm> {
163    fn from(input: &'a Quad<CowTerm<'a>>) -> Self {
164        Self::new((&input.s).into(), (&input.p).into(), (&input.o).into())
165    }
166}
167
168impl<'a> From<Triple<HeapTerm>> for Triple<CowTerm<'a>> {
169    fn from(input: Triple<HeapTerm>) -> Self {
170        Self::new(input.s.into(), input.p.into(), input.o.into())
171    }
172}
173
174impl<'a> From<&'a Triple<HeapTerm>> for Triple<CowTerm<'a>> {
175    fn from(input: &'a Triple<HeapTerm>) -> Self {
176        Self::new((&input.s).into(), (&input.p).into(), (&input.o).into())
177    }
178}
179
180impl<'a> From<Quad<HeapTerm>> for Triple<CowTerm<'a>> {
181    fn from(input: Quad<HeapTerm>) -> Self {
182        Self::new(input.s.into(), input.p.into(), input.o.into())
183    }
184}
185
186impl<'a> From<&'a Quad<HeapTerm>> for Triple<CowTerm<'a>> {
187    fn from(input: &'a Quad<HeapTerm>) -> Self {
188        Self::new((&input.s).into(), (&input.p).into(), (&input.o).into())
189    }
190}
191
192impl<T: Term> From<(T, T, T)> for Triple<T> {
193    fn from((s, p, o): (T, T, T)) -> Self {
194        Self::new(s, p, o)
195    }
196}
197
198impl<T: Term + Clone> From<(&T, &T, &T)> for Triple<T> {
199    fn from((s, p, o): (&T, &T, &T)) -> Self {
200        Self::new(s.clone(), p.clone(), o.clone())
201    }
202}
203
204impl<T: Term> TryFrom<TriplePattern<T>> for Triple<T> {
205    type Error = ();
206
207    fn try_from(input: TriplePattern<T>) -> Result<Self, Self::Error> {
208        if !input.is_constant() {
209            return Err(());
210        }
211        Ok(Self::new(
212            input.s.unwrap(),
213            input.p.unwrap(),
214            input.o.unwrap(),
215        ))
216    }
217}
218
219impl<T: Term> TryFrom<QuadPattern<T>> for Triple<T> {
220    type Error = ();
221
222    fn try_from(input: QuadPattern<T>) -> Result<Self, Self::Error> {
223        if !input.is_constant() {
224            return Err(());
225        }
226        Ok(Self::new(
227            input.s.unwrap(),
228            input.p.unwrap(),
229            input.o.unwrap(),
230        ))
231    }
232}
233
234impl<T: Term> FromIterator<T> for Triple<T> {
235    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
236        let mut iter = iter.into_iter();
237        Self::new(
238            iter.next().unwrap(),
239            iter.next().unwrap(),
240            iter.next().unwrap(),
241        )
242    }
243}