sophia_api/source/
map.rs

1//! I define [`MapTripleSource`] and [`MapQuadSource`],
2//! the result type of [`TripleSource::map_triples`] and [`QuadSource::map_quads`] respectively.
3use super::*;
4use std::collections::VecDeque;
5
6mod _triple {
7    use super::*;
8    use crate::triple::Triple;
9
10    /// The result of [`TripleSource::map_triples`].
11    pub struct MapTripleSource<S, F> {
12        pub(in super::super) source: S,
13        pub(in super::super) map: F,
14    }
15
16    impl<S, F, T> TripleSource for MapTripleSource<S, F>
17    where
18        S: TripleSource,
19        F: FnMut(S::Triple<'_>) -> T,
20        T: Triple,
21    {
22        type Triple<'x> = T;
23        type Error = S::Error;
24
25        fn try_for_some_triple<E, F2>(&mut self, mut f: F2) -> StreamResult<bool, Self::Error, E>
26        where
27            E: Error,
28            F2: FnMut(Self::Triple<'_>) -> Result<(), E>,
29        {
30            let map = &mut self.map;
31            self.source.try_for_some_triple(|t| f((map)(t)))
32        }
33
34        fn size_hint_triples(&self) -> (usize, Option<usize>) {
35            self.source.size_hint_triples()
36        }
37    }
38
39    impl<S, F, T> QuadSource for MapTripleSource<S, F>
40    where
41        S: TripleSource,
42        F: FnMut(S::Triple<'_>) -> T,
43        T: crate::quad::Quad,
44    {
45        type Quad<'x> = T;
46        type Error = S::Error;
47
48        fn try_for_some_quad<E, F2>(&mut self, mut f: F2) -> StreamResult<bool, Self::Error, E>
49        where
50            E: Error,
51            F2: FnMut(Self::Quad<'_>) -> Result<(), E>,
52        {
53            let map = &mut self.map;
54            self.source.try_for_some_triple(|t| f((map)(t)))
55        }
56
57        fn size_hint_quads(&self) -> (usize, Option<usize>) {
58            self.source.size_hint_triples()
59        }
60    }
61
62    impl<S, F, T> IntoIterator for MapTripleSource<S, F>
63    where
64        S: TripleSource,
65        F: FnMut(S::Triple<'_>) -> T,
66    {
67        type Item = Result<T, S::Error>;
68        type IntoIter = MapTripleSourceIterator<S, F, T, S::Error>;
69
70        fn into_iter(self) -> Self::IntoIter {
71            MapTripleSourceIterator {
72                source: self.source,
73                map: self.map,
74                buffer: VecDeque::new(),
75            }
76        }
77    }
78
79    /// [`Iterator`] implementation for the returned value of [`TripleSource::map_triples`]
80    /// or [`QuadSource::map_quads`].
81    pub struct MapTripleSourceIterator<S, F, T, E> {
82        source: S,
83        map: F,
84        buffer: VecDeque<Result<T, E>>,
85    }
86
87    impl<S, F, T> Iterator for MapTripleSourceIterator<S, F, T, S::Error>
88    where
89        S: TripleSource,
90        F: FnMut(S::Triple<'_>) -> T,
91    {
92        type Item = Result<T, S::Error>;
93        fn next(&mut self) -> Option<Result<T, S::Error>> {
94            let mut remaining = true;
95            let mut buffer = VecDeque::new();
96            std::mem::swap(&mut self.buffer, &mut buffer);
97            while buffer.is_empty() && remaining {
98                match self.source.for_some_triple(&mut |i| {
99                    buffer.push_back(Ok((self.map)(i)));
100                }) {
101                    Ok(b) => {
102                        remaining = b;
103                    }
104                    Err(err) => {
105                        buffer.push_back(Err(err));
106                        remaining = false;
107                    }
108                }
109            }
110            std::mem::swap(&mut self.buffer, &mut buffer);
111            self.buffer.pop_front()
112        }
113
114        fn size_hint(&self) -> (usize, Option<usize>) {
115            self.source.size_hint_triples()
116        }
117    }
118}
119pub use _triple::*;
120
121/// Maintenance: any change in the _triple module above
122/// should be reflected in the _quad module below.
123///
124/// An easy way to do this is to replace _quad with the code of _triple,
125/// replacing all occurrences of `Triple` with `Quad`,
126/// and all occurrences of `triple` with `quad`
127/// (modulo some adjustments)
128mod _quad {
129    use super::*;
130    use crate::quad::Quad;
131
132    /// The result of [`QuadSource::map_quads`].
133    pub struct MapQuadSource<S, F> {
134        pub(in super::super) source: S,
135        pub(in super::super) map: F,
136    }
137
138    impl<S, F, T> TripleSource for MapQuadSource<S, F>
139    where
140        S: QuadSource,
141        F: FnMut(S::Quad<'_>) -> T,
142        T: crate::triple::Triple,
143    {
144        type Triple<'x> = T;
145        type Error = S::Error;
146
147        fn try_for_some_triple<E, F2>(&mut self, mut f: F2) -> StreamResult<bool, Self::Error, E>
148        where
149            E: Error,
150            F2: FnMut(Self::Triple<'_>) -> Result<(), E>,
151        {
152            let map = &mut self.map;
153            self.source.try_for_some_quad(|t| f((map)(t)))
154        }
155
156        fn size_hint_triples(&self) -> (usize, Option<usize>) {
157            self.source.size_hint_quads()
158        }
159    }
160
161    impl<S, F, T> QuadSource for MapQuadSource<S, F>
162    where
163        S: QuadSource,
164        F: FnMut(S::Quad<'_>) -> T,
165        T: Quad,
166    {
167        type Quad<'x> = T;
168        type Error = S::Error;
169
170        fn try_for_some_quad<E, F2>(&mut self, mut f: F2) -> StreamResult<bool, Self::Error, E>
171        where
172            E: Error,
173            F2: FnMut(Self::Quad<'_>) -> Result<(), E>,
174        {
175            let map = &mut self.map;
176            self.source.try_for_some_quad(|t| f((map)(t)))
177        }
178
179        fn size_hint_quads(&self) -> (usize, Option<usize>) {
180            self.source.size_hint_quads()
181        }
182    }
183
184    impl<S, F, T> IntoIterator for MapQuadSource<S, F>
185    where
186        S: QuadSource,
187        F: FnMut(S::Quad<'_>) -> T,
188    {
189        type Item = Result<T, S::Error>;
190        type IntoIter = MapQuadSourceIterator<S, F, T, S::Error>;
191
192        fn into_iter(self) -> Self::IntoIter {
193            MapQuadSourceIterator {
194                source: self.source,
195                map: self.map,
196                buffer: VecDeque::new(),
197            }
198        }
199    }
200
201    /// [`Iterator`] implementation for the returned value of [`QuadSource::map_quads`]
202    /// or [`QuadSource::map_quads`].
203    pub struct MapQuadSourceIterator<S, F, T, E> {
204        source: S,
205        map: F,
206        buffer: VecDeque<Result<T, E>>,
207    }
208
209    impl<S, F, T> Iterator for MapQuadSourceIterator<S, F, T, S::Error>
210    where
211        S: QuadSource,
212        F: FnMut(S::Quad<'_>) -> T,
213    {
214        type Item = Result<T, S::Error>;
215        fn next(&mut self) -> Option<Result<T, S::Error>> {
216            let mut remaining = true;
217            let mut buffer = VecDeque::new();
218            std::mem::swap(&mut self.buffer, &mut buffer);
219            while buffer.is_empty() && remaining {
220                match self.source.for_some_quad(&mut |i| {
221                    buffer.push_back(Ok((self.map)(i)));
222                }) {
223                    Ok(b) => {
224                        remaining = b;
225                    }
226                    Err(err) => {
227                        buffer.push_back(Err(err));
228                        remaining = false;
229                    }
230                }
231            }
232            std::mem::swap(&mut self.buffer, &mut buffer);
233            self.buffer.pop_front()
234        }
235
236        fn size_hint(&self) -> (usize, Option<usize>) {
237            self.source.size_hint_quads()
238        }
239    }
240}
241pub use _quad::*;
242
243#[cfg(test)]
244mod test {
245    use super::*;
246    use crate::dataset::{Dataset, MutableDataset};
247    use crate::graph::{Graph, MutableGraph};
248    use crate::quad::{Quad, Spog};
249    use crate::term::ez_term;
250    use crate::term::{SimpleTerm, Term};
251    use crate::triple::Triple;
252
253    // check that the result of TripleSource::map_triples implements the expected traits,
254    // and that they work as expected
255
256    #[test]
257    fn ts_map_to_triples() {
258        let g = vec![
259            [ez_term(":a"), ez_term(":b"), ez_term(":c")],
260            [ez_term(":d"), ez_term(":e"), ez_term(":f")],
261            [ez_term(":g"), ez_term(":h"), ez_term(":i")],
262        ];
263        let mut h: Vec<[SimpleTerm; 3]> = vec![];
264        g.triples()
265            .map_triples(|t| [t.o(), t.p(), t.s()])
266            .for_each_triple(|t| {
267                h.insert_triple(t).unwrap();
268            })
269            .unwrap();
270        assert_eq!(
271            h,
272            vec![
273                [ez_term(":c"), ez_term(":b"), ez_term(":a")],
274                [ez_term(":f"), ez_term(":e"), ez_term(":d")],
275                [ez_term(":i"), ez_term(":h"), ez_term(":g")],
276            ]
277        )
278    }
279
280    #[test]
281    fn ts_map_to_quads() {
282        let g = vec![
283            [ez_term(":a"), ez_term(":b"), ez_term(":c")],
284            [ez_term(":d"), ez_term(":e"), ez_term(":f")],
285            [ez_term(":g"), ez_term(":h"), ez_term(":i")],
286        ];
287        let mut h: Vec<Spog<SimpleTerm>> = vec![];
288        g.triples()
289            .map_triples(|t| ([t.o(), t.p(), t.s()], None))
290            .for_each_quad(|q| {
291                h.insert_quad(q).unwrap();
292            })
293            .unwrap();
294        assert_eq!(
295            h,
296            vec![
297                ([ez_term(":c"), ez_term(":b"), ez_term(":a")], None),
298                ([ez_term(":f"), ez_term(":e"), ez_term(":d")], None),
299                ([ez_term(":i"), ez_term(":h"), ez_term(":g")], None),
300            ]
301        )
302    }
303
304    #[test]
305    fn ts_map_iter() {
306        let g = vec![
307            [ez_term(":a"), ez_term(":b"), ez_term(":c")],
308            [ez_term(":d"), ez_term(":e"), ez_term(":f")],
309            [ez_term(":g"), ez_term(":h"), ez_term(":i")],
310        ];
311        let h: Result<Vec<String>, _> = g
312            .triples()
313            .map_triples(|t| t.s().iri().unwrap().to_string())
314            .into_iter()
315            .collect();
316        assert_eq!(
317            h.unwrap(),
318            vec![
319                "tag:a".to_string(),
320                "tag:d".to_string(),
321                "tag:g".to_string(),
322            ]
323        )
324    }
325
326    // check that the result of QuadSource::map_quads implements the expected traits
327    // and that they work as expected
328
329    #[test]
330    fn qs_map_to_triples() {
331        let d = vec![
332            ([ez_term(":a"), ez_term(":b"), ez_term(":c")], None),
333            ([ez_term(":d"), ez_term(":e"), ez_term(":f")], None),
334            ([ez_term(":g"), ez_term(":h"), ez_term(":i")], None),
335        ];
336        let mut h: Vec<[SimpleTerm; 3]> = vec![];
337        d.quads()
338            .map_quads(|q| [q.o(), q.p(), q.s()])
339            .for_each_triple(|t| {
340                h.insert_triple(t).unwrap();
341            })
342            .unwrap();
343        assert_eq!(
344            h,
345            vec![
346                [ez_term(":c"), ez_term(":b"), ez_term(":a")],
347                [ez_term(":f"), ez_term(":e"), ez_term(":d")],
348                [ez_term(":i"), ez_term(":h"), ez_term(":g")],
349            ]
350        )
351    }
352
353    #[test]
354    fn qs_map_to_quads() {
355        let d = vec![
356            ([ez_term(":a"), ez_term(":b"), ez_term(":c")], None),
357            ([ez_term(":d"), ez_term(":e"), ez_term(":f")], None),
358            ([ez_term(":g"), ez_term(":h"), ez_term(":i")], None),
359        ];
360        let mut h: Vec<Spog<SimpleTerm>> = vec![];
361        d.quads()
362            .map_quads(|q| ([q.o(), q.p(), q.s()], q.g()))
363            .for_each_quad(|q| {
364                h.insert_quad(q).unwrap();
365            })
366            .unwrap();
367        assert_eq!(
368            h,
369            vec![
370                ([ez_term(":c"), ez_term(":b"), ez_term(":a")], None),
371                ([ez_term(":f"), ez_term(":e"), ez_term(":d")], None),
372                ([ez_term(":i"), ez_term(":h"), ez_term(":g")], None),
373            ]
374        )
375    }
376
377    #[test]
378    fn qs_map_iter() {
379        let d = vec![
380            ([ez_term(":a"), ez_term(":b"), ez_term(":c")], None),
381            ([ez_term(":d"), ez_term(":e"), ez_term(":f")], None),
382            ([ez_term(":g"), ez_term(":h"), ez_term(":i")], None),
383        ];
384        let h: Result<Vec<String>, _> = d
385            .quads()
386            .map_quads(|q| q.s().iri().unwrap().to_string())
387            .into_iter()
388            .collect();
389        assert_eq!(
390            h.unwrap(),
391            vec![
392                "tag:a".to_string(),
393                "tag:d".to_string(),
394                "tag:g".to_string(),
395            ]
396        )
397    }
398}