sophia_api/source/
filter.rs

1//! I define [`FilterSource`], the result type of [`Source::filter_items`].
2//! I also define [`FilterTripleSource`] and [`FilterQuadSource`],
3//! which are required to ensure that the output of
4//! [`TripleSource::filter_triples`] and [`QuadSource::filter_quads`]
5//! are recognized as a [`TripleSource`] and a [`QuadSource`], respectively.
6
7use super::*;
8
9/// The result type of [`Source::filter_items`].
10pub struct FilterSource<S, P> {
11    pub(super) source: S,
12    pub(super) predicate: P,
13}
14
15impl<S, P> Source for FilterSource<S, P>
16where
17    S: Source,
18    P: FnMut(&S::Item<'_>) -> bool,
19{
20    type Item<'x> = S::Item<'x>;
21    type Error = S::Error;
22
23    fn try_for_some_item<E, F>(&mut self, mut f: F) -> StreamResult<bool, Self::Error, E>
24    where
25        E: std::error::Error + Send + Sync + 'static,
26        F: FnMut(Self::Item<'_>) -> Result<(), E>,
27    {
28        let p = &mut self.predicate;
29        self.source.try_for_some_item(|i| {
30            if p(&i) {
31                f(i)?;
32            }
33            Ok(())
34        })
35    }
36
37    fn size_hint_items(&self) -> (usize, Option<usize>) {
38        (0, self.source.size_hint_items().1)
39    }
40}
41
42mod _triple {
43    use super::*;
44
45    /// The result type of [`TripleSource::filter_triples`].
46    pub struct FilterTripleSource<S, P>(pub(crate) FilterSource<S, P>);
47
48    impl<S, P> Source for FilterTripleSource<S, P>
49    where
50        S: TripleSource,
51        P: FnMut(&S::Item<'_>) -> bool,
52    {
53        type Item<'x> = TSTriple<'x, S>;
54        type Error = S::Error;
55
56        fn try_for_some_item<E, F>(&mut self, mut f: F) -> StreamResult<bool, Self::Error, E>
57        where
58            E: std::error::Error + Send + Sync + 'static,
59            F: FnMut(Self::Item<'_>) -> Result<(), E>,
60        {
61            self.0.try_for_some_item(|i| f(S::i2t(i)))
62        }
63
64        fn size_hint_items(&self) -> (usize, Option<usize>) {
65            (0, self.0.size_hint_items().1)
66        }
67    }
68}
69pub use _triple::*;
70
71mod _quad {
72    use super::*;
73
74    /// The result type of [`QuadSource::filter_quads`].
75    pub struct FilterQuadSource<S, P>(pub(crate) FilterSource<S, P>);
76
77    impl<S, P> Source for FilterQuadSource<S, P>
78    where
79        S: QuadSource,
80        P: FnMut(&S::Item<'_>) -> bool,
81    {
82        type Item<'x> = QSQuad<'x, S>;
83        type Error = S::Error;
84
85        fn try_for_some_item<E, F>(&mut self, mut f: F) -> StreamResult<bool, Self::Error, E>
86        where
87            E: std::error::Error + Send + Sync + 'static,
88            F: FnMut(Self::Item<'_>) -> Result<(), E>,
89        {
90            self.0.try_for_some_item(|i| f(S::i2q(i)))
91        }
92
93        fn size_hint_items(&self) -> (usize, Option<usize>) {
94            (0, self.0.size_hint_items().1)
95        }
96    }
97}
98pub use _quad::*;
99
100#[cfg(test)]
101mod test {
102    use super::*;
103    use crate::dataset::{Dataset, MutableDataset};
104    use crate::graph::{Graph, MutableGraph};
105    use crate::quad::{Quad, Spog};
106    use crate::term::ez_term;
107    use crate::term::{SimpleTerm, Term};
108    use crate::triple::Triple;
109
110    #[test]
111    fn s_filter_items() {
112        let v = vec!["foo", "bar", "baz"];
113        let mut w = vec![];
114        v.into_iter()
115            .into_source()
116            .filter_items(|t| t.starts_with('b'))
117            .for_each_item(|t| {
118                w.push(t);
119            })
120            .unwrap();
121        assert_eq!(w, vec!["bar", "baz",],)
122    }
123
124    #[test]
125    fn ts_filter_triples() {
126        let g = vec![
127            [ez_term(":a"), ez_term(":b"), ez_term(":c")],
128            [ez_term(":d"), ez_term(":e"), ez_term(":f")],
129            [ez_term(":g"), ez_term(":h"), ez_term(":i")],
130        ];
131        let mut h: Vec<[SimpleTerm; 3]> = vec![];
132        g.triples()
133            .filter_triples(|t| !Term::eq(t.p(), ez_term(":e")))
134            .for_each_triple(|t| {
135                h.insert_triple(t).unwrap();
136            })
137            .unwrap();
138        assert_eq!(
139            h,
140            vec![
141                [ez_term(":a"), ez_term(":b"), ez_term(":c")],
142                [ez_term(":g"), ez_term(":h"), ez_term(":i")],
143            ]
144        )
145    }
146
147    #[test]
148    fn qs_filter_triples() {
149        let d = vec![
150            ([ez_term(":a"), ez_term(":b"), ez_term(":c")], None),
151            ([ez_term(":d"), ez_term(":e"), ez_term(":f")], None),
152            ([ez_term(":g"), ez_term(":h"), ez_term(":i")], None),
153        ];
154        let mut h: Vec<Spog<SimpleTerm>> = vec![];
155        d.quads()
156            .filter_quads(|q| !Term::eq(q.p(), ez_term(":e")))
157            .for_each_quad(|q| {
158                h.insert_quad(q).unwrap();
159            })
160            .unwrap();
161        assert_eq!(
162            h,
163            vec![
164                ([ez_term(":a"), ez_term(":b"), ez_term(":c")], None),
165                ([ez_term(":g"), ez_term(":h"), ez_term(":i")], None),
166            ]
167        )
168    }
169}