1use crate::{
4 CowTerm, HeapTerm, QuadPattern, Statement, StatementPattern, Term, Triple, TriplePattern,
5};
6
7pub type QuadSlot = crate::StatementSlot;
8
9#[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 pub fn has_subject(&self) -> bool {
58 true
59 }
60
61 pub fn has_predicate(&self) -> bool {
63 true
64 }
65
66 pub fn has_object(&self) -> bool {
68 true
69 }
70
71 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}