1use super::*;
3use std::{collections::VecDeque, error::Error};
4
5pub struct FilterMapSource<S, F> {
7 pub(in super::super) source: S,
8 pub(in super::super) filter_map: F,
9}
10
11impl<S, F, T> Source for FilterMapSource<S, F>
12where
13 S: Source,
14 F: FnMut(S::Item<'_>) -> Option<T>,
15{
16 type Item<'x> = T;
17 type Error = S::Error;
18
19 fn try_for_some_item<E, F2>(&mut self, mut f: F2) -> StreamResult<bool, Self::Error, E>
20 where
21 E: Error + Send + Sync + 'static,
22 F2: FnMut(Self::Item<'_>) -> Result<(), E>,
23 {
24 let filter_map = &mut self.filter_map;
25 self.source.try_for_some_item(|t| match (filter_map)(t) {
26 None => Ok(()),
27 Some(out) => f(out),
28 })
29 }
30
31 fn size_hint_items(&self) -> (usize, Option<usize>) {
32 (0, self.source.size_hint_items().1)
33 }
34}
35
36impl<S, F, T> IntoIterator for FilterMapSource<S, F>
37where
38 S: Source,
39 F: FnMut(S::Item<'_>) -> Option<T>,
40{
41 type Item = Result<T, S::Error>;
42 type IntoIter = FilterMapSourceIterator<S, F, T, S::Error>;
43
44 fn into_iter(self) -> Self::IntoIter {
45 FilterMapSourceIterator {
46 source: self.source,
47 filter_map: self.filter_map,
48 buffer: VecDeque::new(),
49 }
50 }
51}
52
53pub struct FilterMapSourceIterator<S, F, T, E> {
55 source: S,
56 filter_map: F,
57 buffer: VecDeque<Result<T, E>>,
58}
59
60impl<S, F, T> Iterator for FilterMapSourceIterator<S, F, T, S::Error>
61where
62 S: Source,
63 F: FnMut(S::Item<'_>) -> Option<T>,
64{
65 type Item = Result<T, S::Error>;
66 fn next(&mut self) -> Option<Result<T, S::Error>> {
67 let mut remaining = true;
68 let mut buffer = VecDeque::new();
69 std::mem::swap(&mut self.buffer, &mut buffer);
70 while buffer.is_empty() && remaining {
71 let resb = self.source.for_some_item(|i| {
72 if let Some(t) = (self.filter_map)(i) {
73 buffer.push_back(Ok(t));
74 }
75 });
76 match resb {
77 Ok(b) => {
78 remaining = b;
79 }
80 Err(err) => {
81 buffer.push_back(Err(err));
82 remaining = false;
83 }
84 }
85 }
86 std::mem::swap(&mut self.buffer, &mut buffer);
87 self.buffer.pop_front()
88 }
89
90 fn size_hint(&self) -> (usize, Option<usize>) {
91 self.source.size_hint_items()
92 }
93}
94
95#[cfg(test)]
96mod test {
97 use super::*;
98 use crate::dataset::{Dataset, MutableDataset};
99 use crate::graph::{Graph, MutableGraph};
100 use crate::quad::{Quad, Spog};
101 use crate::term::ez_term;
102 use crate::term::{SimpleTerm, Term};
103 use crate::triple::Triple;
104
105 #[test]
109 fn ts_filter_map_to_triples() {
110 let g = vec![
111 [ez_term(":a"), ez_term(":b"), ez_term(":c")],
112 [ez_term(":d"), ez_term(":e"), ez_term(":f")],
113 [ez_term(":g"), ez_term(":h"), ez_term(":i")],
114 ];
115 let mut h: Vec<[SimpleTerm; 3]> = vec![];
116 g.triples()
117 .filter_map_triples(|t| {
118 (!Term::eq(t.p(), ez_term(":e"))).then_some([t.o(), t.p(), t.s()])
119 })
120 .for_each_triple(|t| {
121 h.insert_triple(t).unwrap();
122 })
123 .unwrap();
124 assert_eq!(
125 h,
126 vec![
127 [ez_term(":c"), ez_term(":b"), ez_term(":a")],
128 [ez_term(":i"), ez_term(":h"), ez_term(":g")],
129 ]
130 )
131 }
132
133 #[test]
134 fn ts_filter_map_to_quads() {
135 let g = vec![
136 [ez_term(":a"), ez_term(":b"), ez_term(":c")],
137 [ez_term(":g"), ez_term(":h"), ez_term(":i")],
138 ];
139 let mut h: Vec<Spog<SimpleTerm>> = vec![];
140 g.triples()
141 .filter_map_triples(|t| {
142 (!Term::eq(t.p(), ez_term(":e"))).then_some(([t.o(), t.p(), t.s()], None))
143 })
144 .for_each_quad(|q| {
145 h.insert_quad(q).unwrap();
146 })
147 .unwrap();
148 assert_eq!(
149 h,
150 vec![
151 ([ez_term(":c"), ez_term(":b"), ez_term(":a")], None),
152 ([ez_term(":i"), ez_term(":h"), ez_term(":g")], None),
153 ]
154 )
155 }
156
157 #[test]
158 fn ts_filter_map_iter() {
159 let g = vec![
160 [ez_term(":a"), ez_term(":b"), ez_term(":c")],
161 [ez_term(":d"), ez_term(":e"), ez_term(":f")],
162 [ez_term(":g"), ez_term(":h"), ez_term(":i")],
163 ];
164 let h: Result<Vec<String>, _> = g
165 .triples()
166 .filter_map_triples(|t| {
167 (!Term::eq(t.p(), ez_term(":e"))).then_some(t.s().iri().unwrap().to_string())
168 })
169 .into_iter()
170 .collect();
171 assert_eq!(h.unwrap(), vec!["tag:a".to_string(), "tag:g".to_string(),])
172 }
173
174 #[test]
178 fn qs_filter_map_to_triples() {
179 let d = vec![
180 ([ez_term(":a"), ez_term(":b"), ez_term(":c")], None),
181 ([ez_term(":d"), ez_term(":e"), ez_term(":f")], None),
182 ([ez_term(":g"), ez_term(":h"), ez_term(":i")], None),
183 ];
184 let mut h: Vec<[SimpleTerm; 3]> = vec![];
185 d.quads()
186 .filter_map_quads(|q| {
187 (!Term::eq(q.p(), ez_term(":e"))).then_some([q.o(), q.p(), q.s()])
188 })
189 .for_each_triple(|t| {
190 h.insert_triple(t).unwrap();
191 })
192 .unwrap();
193 assert_eq!(
194 h,
195 vec![
196 [ez_term(":c"), ez_term(":b"), ez_term(":a")],
197 [ez_term(":i"), ez_term(":h"), ez_term(":g")],
198 ]
199 )
200 }
201
202 #[test]
203 fn qs_filter_map_to_quads() {
204 let d = vec![
205 ([ez_term(":a"), ez_term(":b"), ez_term(":c")], None),
206 ([ez_term(":d"), ez_term(":e"), ez_term(":f")], None),
207 ([ez_term(":g"), ez_term(":h"), ez_term(":i")], None),
208 ];
209 let mut h: Vec<Spog<SimpleTerm>> = vec![];
210 d.quads()
211 .filter_map_quads(|q| {
212 (!Term::eq(q.p(), ez_term(":e"))).then_some(([q.o(), q.p(), q.s()], q.g()))
213 })
214 .for_each_quad(|q| {
215 h.insert_quad(q).unwrap();
216 })
217 .unwrap();
218 assert_eq!(
219 h,
220 vec![
221 ([ez_term(":c"), ez_term(":b"), ez_term(":a")], None),
222 ([ez_term(":i"), ez_term(":h"), ez_term(":g")], None),
223 ]
224 )
225 }
226
227 #[test]
228 fn qs_filter_map_iter() {
229 let d = vec![
230 ([ez_term(":a"), ez_term(":b"), ez_term(":c")], None),
231 ([ez_term(":d"), ez_term(":e"), ez_term(":f")], None),
232 ([ez_term(":g"), ez_term(":h"), ez_term(":i")], None),
233 ];
234 let h: Result<Vec<String>, _> = d
235 .quads()
236 .filter_map_quads(|q| {
237 (!Term::eq(q.p(), ez_term(":e"))).then_some(q.s().iri().unwrap().to_string())
238 })
239 .into_iter()
240 .collect();
241 assert_eq!(h.unwrap(), vec!["tag:a".to_string(), "tag:g".to_string(),])
242 }
243}