Skip to main content

rdf_model/
triple_pattern.rs

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