1use std::{cmp::Ordering, fmt};
2
3use iref::{Iri, IriBuf};
4
5use crate::{
6 vocabulary::{
7 ByRef, EmbedIntoVocabulary, EmbeddedIntoVocabulary, ExtractFromVocabulary,
8 ExtractedFromVocabulary,
9 },
10 Id, LexicalObjectRef, LexicalSubjectRef, Object, Quad, RdfDisplay, Term,
11};
12
13#[cfg(feature = "contextual")]
14use contextual::{DisplayWithContext, WithContext};
15
16#[cfg(feature = "contextual")]
17use crate::RdfDisplayWithContext;
18
19pub type LexicalTriple = Triple<Id, IriBuf, Object>;
21
22pub type LexicalTripleRef<'a> = Triple<LexicalSubjectRef<'a>, &'a Iri, LexicalObjectRef<'a>>;
24
25#[derive(Clone, Copy, Eq, Ord, Hash, Debug)]
27#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
28pub struct Triple<S = Term, P = S, O = S>(pub S, pub P, pub O);
29
30impl<S1: PartialEq<S2>, P1: PartialEq<P2>, O1: PartialEq<O2>, S2, P2, O2>
31 PartialEq<Triple<S2, P2, O2>> for Triple<S1, P1, O1>
32{
33 fn eq(&self, other: &Triple<S2, P2, O2>) -> bool {
34 self.0 == other.0 && self.1 == other.1 && self.2 == other.2
35 }
36}
37
38impl<S1: PartialOrd<S2>, P1: PartialOrd<P2>, O1: PartialOrd<O2>, S2, P2, O2>
39 PartialOrd<Triple<S2, P2, O2>> for Triple<S1, P1, O1>
40{
41 fn partial_cmp(&self, other: &Triple<S2, P2, O2>) -> Option<Ordering> {
42 match self.0.partial_cmp(&other.0) {
43 Some(Ordering::Equal) => match self.1.partial_cmp(&other.1) {
44 Some(Ordering::Equal) => self.2.partial_cmp(&other.2),
45 cmp => cmp,
46 },
47 cmp => cmp,
48 }
49 }
50}
51
52impl<S, P, O> Triple<S, P, O> {
53 pub fn new(subject: S, predicate: P, object: O) -> Self {
55 Self(subject, predicate, object)
56 }
57
58 pub fn subject(&self) -> &S {
61 &self.0
62 }
63
64 pub fn subject_mut(&mut self) -> &mut S {
67 &mut self.0
68 }
69
70 pub fn into_subject(self) -> S {
73 self.0
74 }
75
76 pub fn predicate(&self) -> &P {
79 &self.1
80 }
81
82 pub fn predicate_mut(&mut self) -> &mut P {
85 &mut self.1
86 }
87
88 pub fn into_predicate(self) -> P {
91 self.1
92 }
93
94 pub fn object(&self) -> &O {
97 &self.2
98 }
99
100 pub fn object_mut(&mut self) -> &mut O {
103 &mut self.2
104 }
105
106 pub fn into_object(self) -> O {
109 self.2
110 }
111
112 pub fn into_parts(self) -> (S, P, O) {
114 (self.0, self.1, self.2)
115 }
116
117 pub fn into_quad<G>(self, graph: Option<G>) -> Quad<S, P, O, G> {
119 Quad(self.0, self.1, self.2, graph)
120 }
121
122 pub fn map_subject<U>(self, f: impl FnOnce(S) -> U) -> Triple<U, P, O> {
124 Triple(f(self.0), self.1, self.2)
125 }
126
127 pub fn map_predicate<U>(self, f: impl FnOnce(P) -> U) -> Triple<S, U, O> {
129 Triple(self.0, f(self.1), self.2)
130 }
131
132 pub fn map_object<U>(self, f: impl FnOnce(O) -> U) -> Triple<S, P, U> {
134 Triple(self.0, self.1, f(self.2))
135 }
136
137 pub fn as_ref(&self) -> Triple<&S, &P, &O> {
139 Triple(&self.0, &self.1, &self.2)
140 }
141}
142
143impl<S, P, O> Triple<&S, &P, &O> {
144 pub fn cloned(&self) -> Triple<S, P, O>
145 where
146 S: Clone,
147 P: Clone,
148 O: Clone,
149 {
150 Triple(self.0.clone(), self.1.clone(), self.2.clone())
151 }
152
153 pub fn into_cloned(self) -> Triple<S, P, O>
154 where
155 S: Clone,
156 P: Clone,
157 O: Clone,
158 {
159 Triple(self.0.clone(), self.1.clone(), self.2.clone())
160 }
161}
162
163impl<S, P, O> Triple<&S, &P, &O> {
164 pub fn copied(&self) -> Triple<S, P, O>
165 where
166 S: Copy,
167 P: Copy,
168 O: Copy,
169 {
170 Triple(*self.0, *self.1, *self.2)
171 }
172
173 pub fn into_copied(self) -> Triple<S, P, O>
174 where
175 S: Copy,
176 P: Copy,
177 O: Copy,
178 {
179 Triple(*self.0, *self.1, *self.2)
180 }
181}
182
183impl<T> Triple<T, T, T> {
184 pub fn map<U>(self, mut f: impl FnMut(T) -> U) -> Triple<U, U, U> {
186 Triple(f(self.0), f(self.1), f(self.2))
187 }
188}
189
190impl LexicalTriple {
191 pub fn as_lexical_triple_ref(&self) -> LexicalTripleRef {
192 Triple(
193 self.0.as_lexical_subject_ref(),
194 self.1.as_iri(),
195 self.2.as_lexical_object_ref(),
196 )
197 }
198}
199
200impl LexicalTripleRef<'_> {
201 pub fn into_owned(self) -> LexicalTriple {
202 Triple(self.0.into_owned(), self.1.to_owned(), self.2.into_owned())
203 }
204}
205
206impl<V, S: ExtractFromVocabulary<V>, P: ExtractFromVocabulary<V>, O: ExtractFromVocabulary<V>>
207 ExtractFromVocabulary<V> for Triple<S, P, O>
208{
209 type Extracted = Triple<S::Extracted, P::Extracted, O::Extracted>;
210
211 fn extract_from_vocabulary(self, vocabulary: &V) -> Self::Extracted {
212 Triple(
213 self.0.extract_from_vocabulary(vocabulary),
214 self.1.extract_from_vocabulary(vocabulary),
215 self.2.extract_from_vocabulary(vocabulary),
216 )
217 }
218}
219
220impl<V, S, P, O> ExtractFromVocabulary<V> for ByRef<Triple<S, P, O>>
221where
222 ByRef<S>: ExtractFromVocabulary<V>,
223 ByRef<P>: ExtractFromVocabulary<V>,
224 ByRef<O>: ExtractFromVocabulary<V>,
225{
226 type Extracted = Triple<
227 <ByRef<S> as ExtractFromVocabulary<V>>::Extracted,
228 <ByRef<P> as ExtractFromVocabulary<V>>::Extracted,
229 <ByRef<O> as ExtractFromVocabulary<V>>::Extracted,
230 >;
231
232 fn extract_from_vocabulary(self, vocabulary: &V) -> Self::Extracted {
233 Triple(
234 ByRef(self.0 .0).extract_from_vocabulary(vocabulary),
235 ByRef(self.0 .1).extract_from_vocabulary(vocabulary),
236 ByRef(self.0 .2).extract_from_vocabulary(vocabulary),
237 )
238 }
239}
240
241impl<
242 V,
243 S: ExtractedFromVocabulary<V>,
244 P: ExtractedFromVocabulary<V>,
245 O: ExtractedFromVocabulary<V>,
246 > ExtractedFromVocabulary<V> for Triple<S, P, O>
247{
248 type Extracted = Triple<S::Extracted, P::Extracted, O::Extracted>;
249
250 fn extracted_from_vocabulary(&self, vocabulary: &V) -> Self::Extracted {
251 Triple(
252 self.0.extracted_from_vocabulary(vocabulary),
253 self.1.extracted_from_vocabulary(vocabulary),
254 self.2.extracted_from_vocabulary(vocabulary),
255 )
256 }
257}
258
259impl<V, S: EmbedIntoVocabulary<V>, P: EmbedIntoVocabulary<V>, O: EmbedIntoVocabulary<V>>
260 EmbedIntoVocabulary<V> for Triple<S, P, O>
261{
262 type Embedded = Triple<S::Embedded, P::Embedded, O::Embedded>;
263
264 fn embed_into_vocabulary(self, vocabulary: &mut V) -> Self::Embedded {
265 Triple(
266 self.0.embed_into_vocabulary(vocabulary),
267 self.1.embed_into_vocabulary(vocabulary),
268 self.2.embed_into_vocabulary(vocabulary),
269 )
270 }
271}
272
273impl<
274 V,
275 S: EmbeddedIntoVocabulary<V>,
276 P: EmbeddedIntoVocabulary<V>,
277 O: EmbeddedIntoVocabulary<V>,
278 > EmbeddedIntoVocabulary<V> for Triple<S, P, O>
279{
280 type Embedded = Triple<S::Embedded, P::Embedded, O::Embedded>;
281
282 fn embedded_into_vocabulary(&self, vocabulary: &mut V) -> Self::Embedded {
283 Triple(
284 self.0.embedded_into_vocabulary(vocabulary),
285 self.1.embedded_into_vocabulary(vocabulary),
286 self.2.embedded_into_vocabulary(vocabulary),
287 )
288 }
289}
290
291impl<S: RdfDisplay, P: RdfDisplay, O: RdfDisplay> fmt::Display for Triple<S, P, O> {
292 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
293 write!(
294 f,
295 "{} {} {}",
296 self.0.rdf_display(),
297 self.1.rdf_display(),
298 self.2.rdf_display()
299 )
300 }
301}
302
303impl<S: RdfDisplay, P: RdfDisplay, O: RdfDisplay> RdfDisplay for Triple<S, P, O> {
304 fn rdf_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
305 write!(
306 f,
307 "{} {} {}",
308 self.0.rdf_display(),
309 self.1.rdf_display(),
310 self.2.rdf_display()
311 )
312 }
313}
314
315#[cfg(feature = "contextual")]
316impl<S: RdfDisplayWithContext<V>, P: RdfDisplayWithContext<V>, O: RdfDisplayWithContext<V>, V>
317 DisplayWithContext<V> for Triple<S, P, O>
318{
319 fn fmt_with(&self, vocabulary: &V, f: &mut fmt::Formatter) -> fmt::Result {
320 write!(
321 f,
322 "{} {} {}",
323 self.0.with(vocabulary).rdf_display(),
324 self.1.with(vocabulary).rdf_display(),
325 self.2.with(vocabulary).rdf_display()
326 )
327 }
328}
329
330#[cfg(feature = "contextual")]
331impl<S: RdfDisplayWithContext<V>, P: RdfDisplayWithContext<V>, O: RdfDisplayWithContext<V>, V>
332 RdfDisplayWithContext<V> for Triple<S, P, O>
333{
334 fn rdf_fmt_with(&self, vocabulary: &V, f: &mut fmt::Formatter) -> fmt::Result {
335 write!(
336 f,
337 "{} {} {}",
338 self.0.with(vocabulary).rdf_display(),
339 self.1.with(vocabulary).rdf_display(),
340 self.2.with(vocabulary).rdf_display()
341 )
342 }
343}