Skip to main content

rdf_model/
quad_pattern.rs

1// This is free and unencumbered software released into the public domain.
2
3use crate::{CowTerm, HeapTerm, StatementPattern, Term, TriplePattern};
4
5pub static EMPTY_COW_QUAD_PATTERN: QuadPattern<CowTerm> = QuadPattern::EMPTY;
6pub static EMPTY_HEAP_QUAD_PATTERN: QuadPattern<HeapTerm> = QuadPattern::EMPTY;
7
8/// A quad statement pattern.
9#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11pub struct QuadPattern<T: Term> {
12    pub(crate) s: Option<T>,
13    pub(crate) p: Option<T>,
14    pub(crate) o: Option<T>,
15    pub(crate) g: Option<T>,
16}
17
18impl<T: Term> Default for QuadPattern<T> {
19    fn default() -> Self {
20        Self::EMPTY
21    }
22}
23
24impl<T: Term> QuadPattern<T> {
25    pub const EMPTY: QuadPattern<T> = Self::empty();
26
27    pub const fn empty() -> Self {
28        Self::new(None, None, None, None)
29    }
30
31    pub const fn new(s: Option<T>, p: Option<T>, o: Option<T>, g: Option<T>) -> Self {
32        Self { s, p, o, g }
33    }
34
35    pub const fn with_subject(s: T) -> Self {
36        Self::new(Some(s), None, None, None)
37    }
38
39    pub const fn with_predicate(p: T) -> Self {
40        Self::new(None, Some(p), None, None)
41    }
42
43    pub const fn with_object(o: T) -> Self {
44        Self::new(None, None, Some(o), None)
45    }
46
47    pub const fn with_context(g: T) -> Self {
48        Self::new(None, None, None, Some(g))
49    }
50
51    pub fn is_empty(&self) -> bool {
52        self.s.is_none() && self.p.is_none() && self.o.is_none() && self.g.is_none()
53    }
54
55    pub fn is_constant(&self) -> bool {
56        self.s.is_some() && self.p.is_some() && self.o.is_some() && self.g.is_some()
57    }
58
59    pub fn is_variable(&self) -> bool {
60        !self.is_constant()
61    }
62
63    pub fn into_inner(self) -> (Option<T>, Option<T>, Option<T>, Option<T>) {
64        (self.s, self.p, self.o, self.g)
65    }
66}
67
68impl<T: Term + Clone> QuadPattern<T> {
69    pub fn to_triple_pattern(&self) -> TriplePattern<T> {
70        TriplePattern::new(self.s.clone(), self.p.clone(), self.o.clone())
71    }
72}
73
74impl<T: Term + Clone> StatementPattern for QuadPattern<T> {
75    type Term = T;
76
77    fn subject(&self) -> Option<&Self::Term> {
78        self.s.as_ref()
79    }
80
81    fn predicate(&self) -> Option<&Self::Term> {
82        self.p.as_ref()
83    }
84
85    fn object(&self) -> Option<&Self::Term> {
86        self.o.as_ref()
87    }
88
89    fn context(&self) -> Option<&Self::Term> {
90        self.g.as_ref()
91    }
92}
93
94impl<T: Term> From<()> for QuadPattern<T> {
95    fn from(_: ()) -> Self {
96        Self::default()
97    }
98}
99
100impl<T: Term> From<Option<()>> for QuadPattern<T> {
101    fn from(_: Option<()>) -> Self {
102        Self::default()
103    }
104}
105
106impl<T: Term> From<(T, T, T)> for QuadPattern<T> {
107    fn from((s, p, o): (T, T, T)) -> Self {
108        Self::from((Some(s), Some(p), Some(o)))
109    }
110}
111
112impl<T: Term> From<(Option<T>, Option<T>, Option<T>)> for QuadPattern<T> {
113    fn from((s, p, o): (Option<T>, Option<T>, Option<T>)) -> Self {
114        Self { s, p, o, g: None }
115    }
116}
117
118impl<T: Term + Clone> From<(&T, &T, &T)> for QuadPattern<T> {
119    fn from((s, p, o): (&T, &T, &T)) -> Self {
120        Self::from((Some(s), Some(p), Some(o)))
121    }
122}
123
124impl<T: Term + Clone> From<(Option<&T>, Option<&T>, Option<&T>)> for QuadPattern<T> {
125    fn from((s, p, o): (Option<&T>, Option<&T>, Option<&T>)) -> Self {
126        Self {
127            s: s.cloned(),
128            p: p.cloned(),
129            o: o.cloned(),
130            g: None,
131        }
132    }
133}
134
135impl<T: Term> From<(T, T, T, T)> for QuadPattern<T> {
136    fn from((s, p, o, g): (T, T, T, T)) -> Self {
137        Self::from((Some(s), Some(p), Some(o), Some(g)))
138    }
139}
140
141impl<T: Term> From<(Option<T>, Option<T>, Option<T>, Option<T>)> for QuadPattern<T> {
142    fn from((s, p, o, g): (Option<T>, Option<T>, Option<T>, Option<T>)) -> Self {
143        Self { s, p, o, g }
144    }
145}
146
147impl<T: Term + Clone> From<(&T, &T, &T, &T)> for QuadPattern<T> {
148    fn from((s, p, o, g): (&T, &T, &T, &T)) -> Self {
149        Self::from((Some(s), Some(p), Some(o), Some(g)))
150    }
151}
152
153impl<T: Term + Clone> From<(Option<&T>, Option<&T>, Option<&T>, Option<&T>)> for QuadPattern<T> {
154    fn from((s, p, o, g): (Option<&T>, Option<&T>, Option<&T>, Option<&T>)) -> Self {
155        Self {
156            s: s.cloned(),
157            p: p.cloned(),
158            o: o.cloned(),
159            g: g.cloned(),
160        }
161    }
162}
163
164impl<T: Term> FromIterator<T> for QuadPattern<T> {
165    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
166        let mut iter = iter.into_iter();
167        Self::new(
168            Some(iter.next().unwrap()),
169            Some(iter.next().unwrap()),
170            Some(iter.next().unwrap()),
171            Some(iter.next().unwrap()),
172        )
173    }
174}