Skip to main content

rdf_model/
quad.rs

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