1use 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#[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}