1use super::*;
2use crate::dataset::{CollectibleDataset, Dataset, MutableDataset};
3use crate::quad::Quad;
4
5pub trait QuadSource {
17 type Quad<'x>: Quad;
19 type Error: Error + 'static;
21
22 fn try_for_some_quad<E, F>(&mut self, f: F) -> StreamResult<bool, Self::Error, E>
28 where
29 E: Error,
30 F: FnMut(Self::Quad<'_>) -> Result<(), E>;
31
32 #[inline]
36 fn try_for_each_quad<F, E>(&mut self, mut f: F) -> StreamResult<(), Self::Error, E>
37 where
38 F: FnMut(Self::Quad<'_>) -> Result<(), E>,
39 E: Error,
40 {
41 while self.try_for_some_quad(&mut f)? {}
42 Ok(())
43 }
44
45 #[inline]
51 fn for_some_quad<F>(&mut self, f: &mut F) -> Result<bool, Self::Error>
52 where
53 F: FnMut(Self::Quad<'_>),
54 {
55 self.try_for_some_quad(|t| -> Result<(), Self::Error> {
56 f(t);
57 Ok(())
58 })
59 .map_err(StreamError::inner_into)
60 }
61
62 #[inline]
66 fn for_each_quad<F>(&mut self, f: F) -> Result<(), Self::Error>
67 where
68 F: FnMut(Self::Quad<'_>),
69 {
70 let mut f = f;
71 while self.for_some_quad(&mut f)? {}
72 Ok(())
73 }
74
75 #[inline]
77 fn filter_quads<F>(self, predicate: F) -> filter::FilterQuadSource<Self, F>
78 where
79 Self: Sized,
80 F: FnMut(&Self::Quad<'_>) -> bool,
81 {
82 filter::FilterQuadSource {
83 source: self,
84 predicate,
85 }
86 }
87
88 #[inline]
92 fn filter_map_quads<F, T>(self, filter_map: F) -> filter_map::FilterMapQuadSource<Self, F>
93 where
94 Self: Sized,
95 F: FnMut(Self::Quad<'_>) -> Option<T>,
96 {
97 filter_map::FilterMapQuadSource {
98 source: self,
99 filter_map,
100 }
101 }
102
103 #[inline]
118 fn map_quads<F, T>(self, map: F) -> map::MapQuadSource<Self, F>
119 where
120 Self: Sized,
121 F: FnMut(Self::Quad<'_>) -> T,
122 {
123 map::MapQuadSource { source: self, map }
124 }
125
126 fn to_triples(self) -> convert::ToTriples<Self>
128 where
129 Self: Sized,
130 {
131 convert::ToTriples(self)
132 }
133
134 fn size_hint_quads(&self) -> (usize, Option<usize>) {
138 (0, None)
139 }
140
141 #[inline]
143 fn collect_quads<D>(self) -> StreamResult<D, Self::Error, <D as Dataset>::Error>
144 where
145 Self: Sized,
146 for<'x> Self::Quad<'x>: Quad,
147 D: CollectibleDataset,
148 {
149 D::from_quad_source(self)
150 }
151
152 #[inline]
156 fn add_to_dataset<D: MutableDataset>(
157 self,
158 dataset: &mut D,
159 ) -> StreamResult<usize, Self::Error, <D as MutableDataset>::MutationError>
160 where
161 Self: Sized,
162 for<'x> Self::Quad<'x>: Quad,
163 {
164 dataset.insert_all(self)
165 }
166}
167
168impl<'a, I, T, E> QuadSource for I
169where
170 I: Iterator<Item = Result<T, E>> + 'a,
171 T: Quad,
172 E: Error + 'static,
173{
174 type Quad<'x> = T;
175 type Error = E;
176
177 fn try_for_some_quad<E2, F>(&mut self, mut f: F) -> StreamResult<bool, Self::Error, E2>
178 where
179 E2: Error,
180 F: FnMut(Self::Quad<'_>) -> Result<(), E2>,
181 {
182 match self.next() {
183 Some(Err(e)) => Err(SourceError(e)),
184 Some(Ok(t)) => {
185 f(t).map_err(SinkError)?;
186 Ok(true)
187 }
188 None => Ok(false),
189 }
190 }
191
192 fn size_hint_quads(&self) -> (usize, Option<usize>) {
193 self.size_hint()
194 }
195}
196
197pub trait IntoQuadSource: Iterator + Sized {
200 #[allow(clippy::type_complexity)]
202 fn into_quad_source(
203 self,
204 ) -> std::iter::Map<
205 Self,
206 fn(<Self as Iterator>::Item) -> Result<<Self as Iterator>::Item, Infallible>,
207 > {
208 self.map(Ok::<_, Infallible>)
209 }
210}
211
212impl<I> IntoQuadSource for I
213where
214 I: Iterator,
215 I::Item: Quad,
216{
217}
218
219#[cfg(test)]
220mod check_quad_source {
221 use super::*;
222 use crate::quad::Spog;
223 use crate::term::{SimpleTerm, Term};
224 use sophia_iri::IriRef;
225 use std::convert::Infallible;
226 use std::fmt::Write;
227
228 #[allow(dead_code)] pub fn check_for_each<TS>(ts: TS)
230 where
231 TS: QuadSource,
232 {
233 ts.filter_quads(|t| t.s().is_iri())
234 .for_each_quad(|t| println!("{:?}", t.s()))
235 .unwrap();
236 }
237
238 #[allow(dead_code)] fn check_quad_source_impl_generic_dataset<D: Dataset>(d: &D) {
240 d.quads()
241 .filter_quads(|t| t.s().is_iri())
242 .for_each_quad(|t| println!("{:?}", t.s()))
243 .unwrap();
244 }
245
246 #[allow(dead_code)] fn check_quad_source_impl_concrete_dataset(d: &[Spog<SimpleTerm>]) {
248 d.quads()
249 .filter_quads(|t| t.s().is_iri())
250 .for_each_quad(|t| println!("{:?}", t.s()))
251 .unwrap();
252 }
253
254 struct DummyParser<'a> {
256 tokens: &'a [usize],
257 pos: usize,
258 buffers: [String; 3],
259 }
260
261 impl<'a> QuadSource for DummyParser<'a> {
262 type Quad<'x> = Spog<SimpleTerm<'x>>;
263 type Error = Infallible;
264
265 fn try_for_some_quad<E2, F>(&mut self, mut f: F) -> StreamResult<bool, Self::Error, E2>
266 where
267 E2: Error,
268 F: FnMut(Self::Quad<'_>) -> Result<(), E2>,
269 {
270 if self.tokens.len() - self.pos < 3 {
271 Ok(false)
272 } else {
273 for i in 0..3 {
274 write!(&mut self.buffers[i], "b{}", self.tokens[self.pos + i]).unwrap();
275 }
276 let q = (
277 [
278 IriRef::new_unchecked(&self.buffers[0][..]).into_term(),
279 IriRef::new_unchecked(&self.buffers[1][..]).into_term(),
280 IriRef::new_unchecked(&self.buffers[2][..]).into_term(),
281 ],
282 None,
283 );
284 f(q).map_err(SinkError).map(|_| true)
285 }
286 }
287 }
288
289 #[allow(dead_code)] fn check_quad_source_impl_by_iterator(v: Vec<Result<Spog<SimpleTerm>, std::io::Error>>) {
291 v.into_iter()
292 .for_each_quad(|q| println!("{:?}", q.s()))
293 .unwrap();
294 }
295
296 }