sophia_api/term/matcher/
_graph_name_matcher.rs

1use super::*;
2
3/// Generic trait for matching [`GraphName`]s.
4pub trait GraphNameMatcher {
5    /// The type of term that this GraphNameMatcher contains
6    type Term: Term + ?Sized;
7
8    /// Check whether this matcher matches `t`.
9    fn matches<T2: Term + ?Sized>(&self, graph_name: GraphName<&T2>) -> bool;
10
11    /// Return `None`, unless this matcher can only match a single graph name,
12    /// in which case this method may return that graph name.
13    ///
14    /// This method is provided for optimization purposes,
15    /// so implementing it is optional.
16    fn constant(&self) -> Option<GraphName<&Self::Term>> {
17        None
18    }
19
20    /// Return a [`GraphNameMatcher`] that is actually just a reference to this one.
21    fn matcher_ref(&self) -> MatcherRef<'_, Self> {
22        MatcherRef(self)
23    }
24}
25
26impl<T> GraphNameMatcher for Option<Option<T>>
27where
28    T: Term,
29{
30    type Term = T;
31
32    fn matches<T2: Term + ?Sized>(&self, graph_name: GraphName<&T2>) -> bool {
33        match self {
34            Some(mine) => graph_name_eq(
35                mine.as_ref().map(|gn| gn.borrow_term()),
36                graph_name.map(|gn| gn.borrow_term()),
37            ),
38            None => false,
39        }
40    }
41    fn constant(&self) -> Option<GraphName<&Self::Term>> {
42        self.as_ref().map(GraphName::as_ref)
43    }
44}
45
46impl<T, const N: usize> GraphNameMatcher for [GraphName<T>; N]
47where
48    T: Term,
49{
50    type Term = T;
51
52    fn matches<T2: Term + ?Sized>(&self, graph_name: GraphName<&T2>) -> bool {
53        self.iter().any(|mine| {
54            graph_name_eq(
55                mine.as_ref().map(|gn| gn.borrow_term()),
56                graph_name.map(|gn| gn.borrow_term()),
57            )
58        })
59    }
60    fn constant(&self) -> Option<GraphName<&Self::Term>> {
61        if N == 1 {
62            Some(self[0].as_ref())
63        } else {
64            None
65        }
66    }
67}
68
69impl<T> GraphNameMatcher for &[GraphName<T>]
70where
71    T: Term,
72{
73    type Term = T;
74
75    fn matches<T2: Term + ?Sized>(&self, graph_name: GraphName<&T2>) -> bool {
76        self.iter().any(|mine| {
77            graph_name_eq(
78                mine.as_ref().map(|gn| gn.borrow_term()),
79                graph_name.map(|gn| gn.borrow_term()),
80            )
81        })
82    }
83    fn constant(&self) -> Option<GraphName<&Self::Term>> {
84        if self.len() == 1 {
85            Some(self[0].as_ref())
86        } else {
87            None
88        }
89    }
90}
91
92impl GraphNameMatcher for Option<TermKind> {
93    type Term = SimpleTerm<'static>; // not actually used
94
95    fn matches<T2: Term + ?Sized>(&self, graph_name: GraphName<&T2>) -> bool {
96        graph_name.map(Term::kind) == *self
97    }
98}
99
100/// Matches only embedded triple whose components match the corresponding matchers.
101impl<S, P, O> GraphNameMatcher for Option<(S, P, O)>
102where
103    S: TermMatcher,
104    P: TermMatcher,
105    O: TermMatcher,
106{
107    type Term = S::Term; // not actually used
108
109    fn matches<T2: Term + ?Sized>(&self, graph_name: Option<&T2>) -> bool {
110        match (self, graph_name.map(Term::triple)) {
111            (None, None) => true,
112            (Some((sm, pm, om)), Some(Some(t))) => {
113                t.matched_by(sm.matcher_ref(), pm.matcher_ref(), om.matcher_ref())
114            }
115            _ => false,
116        }
117    }
118}
119
120impl<F> GraphNameMatcher for F
121where
122    F: Fn(GraphName<SimpleTerm>) -> bool + ?Sized,
123{
124    type Term = SimpleTerm<'static>; // not actually used
125
126    fn matches<T2: Term + ?Sized>(&self, graph_name: GraphName<&T2>) -> bool {
127        (self)(graph_name.map(Term::as_simple))
128    }
129}
130
131impl GraphNameMatcher for Any {
132    type Term = SimpleTerm<'static>;
133
134    fn matches<T2: Term + ?Sized>(&self, _: GraphName<&T2>) -> bool {
135        true
136    }
137}