1#![warn(missing_docs)]
2use std::iter::FusedIterator;
38
39pub trait IntoContextIterator: Iterator {
43 fn with_context<Ctx>(self, context: Ctx) -> WithCtx<Self, Ctx>
45 where
46 Self: Sized,
47 {
48 WithCtx {
49 iter: self,
50 context,
51 }
52 }
53}
54
55impl<I> IntoContextIterator for I where I: Iterator {}
56
57pub trait ContextIterator: Iterator {
59 type Context;
61
62 fn context(&self) -> &Self::Context;
64
65 fn context_map<F, O>(self, map: F) -> CtxMap<Self, F>
67 where
68 Self: Sized,
69 F: Fn(&Self::Context) -> &O,
70 {
71 CtxMap { iter: self, map }
72 }
73
74 fn map_with_context<O>(self, map: fn(Self::Item, &Self::Context) -> O) -> MapCtx<Self, O>
76 where
77 Self: Sized,
78 {
79 MapCtx { iter: self, map }
80 }
81
82 fn filter_with_context(self, filter: fn(&Self::Item, &Self::Context) -> bool) -> FilterCtx<Self>
84 where
85 Self: Sized,
86 {
87 FilterCtx {
88 iter: self,
89 predicate: filter,
90 }
91 }
92
93 fn filter_map_with_context<O>(
95 self,
96 filter: fn(Self::Item, &Self::Context) -> Option<O>,
97 ) -> FilterMapCtx<Self, O>
98 where
99 Self: Sized,
100 {
101 FilterMapCtx {
102 iter: self,
103 predicate: filter,
104 }
105 }
106}
107
108#[derive(Clone, Debug)]
110pub struct WithCtx<I, Ctx> {
111 pub(self) iter: I,
112 pub(self) context: Ctx,
113}
114
115impl<I, Ctx> Iterator for WithCtx<I, Ctx>
116where
117 I: Iterator,
118{
119 type Item = I::Item;
120
121 fn next(&mut self) -> Option<Self::Item> {
122 self.iter.next()
123 }
124
125 fn count(self) -> usize {
126 self.iter.count()
127 }
128
129 fn size_hint(&self) -> (usize, Option<usize>) {
130 (0, self.iter.size_hint().1)
131 }
132}
133
134impl<I, Ctx> ContextIterator for WithCtx<I, Ctx>
135where
136 I: Iterator,
137{
138 type Context = Ctx;
139
140 fn context(&self) -> &Self::Context {
141 &self.context
142 }
143}
144
145impl<I, Ctx> DoubleEndedIterator for WithCtx<I, Ctx>
146where
147 I: DoubleEndedIterator,
148{
149 fn next_back(&mut self) -> Option<Self::Item> {
150 self.iter.next_back()
151 }
152}
153
154impl<I, Ctx> ExactSizeIterator for WithCtx<I, Ctx>
155where
156 I: ExactSizeIterator,
157{
158 fn len(&self) -> usize {
159 self.iter.len()
160 }
161}
162
163impl<I, Ctx> FusedIterator for WithCtx<I, Ctx> where I: FusedIterator {}
164
165#[derive(Clone, Debug)]
167pub struct CtxMap<I, F> {
168 pub(self) iter: I,
169 pub(self) map: F,
170}
171
172impl<I, F> Iterator for CtxMap<I, F>
173where
174 I: Iterator,
175{
176 type Item = I::Item;
177
178 fn next(&mut self) -> Option<Self::Item> {
179 self.iter.next()
180 }
181
182 fn count(self) -> usize {
183 self.iter.count()
184 }
185
186 fn size_hint(&self) -> (usize, Option<usize>) {
187 self.iter.size_hint()
188 }
189}
190
191impl<I, F, O> ContextIterator for CtxMap<I, F>
192where
193 I: ContextIterator,
194 F: Fn(&I::Context) -> &O,
195{
196 type Context = O;
197
198 fn context(&self) -> &O {
199 (self.map)(self.iter.context())
200 }
201}
202
203impl<I, F> DoubleEndedIterator for CtxMap<I, F>
204where
205 I: DoubleEndedIterator,
206{
207 fn next_back(&mut self) -> Option<Self::Item> {
208 self.iter.next_back()
209 }
210}
211
212impl<I, F> ExactSizeIterator for CtxMap<I, F>
213where
214 I: ExactSizeIterator,
215{
216 fn len(&self) -> usize {
217 self.iter.len()
218 }
219}
220
221impl<I, Ctx> FusedIterator for CtxMap<I, Ctx> where I: FusedIterator {}
222
223pub type MapWithCtx<I, Ctx, O> = MapCtx<WithCtx<I, Ctx>, O>;
226
227#[derive(Clone, Debug)]
232pub struct MapCtx<I, O>
233where
234 I: ContextIterator,
235{
236 pub(self) iter: I,
237 pub(self) map: fn(I::Item, &I::Context) -> O,
238}
239
240impl<I, O> Iterator for MapCtx<I, O>
241where
242 I: ContextIterator,
243{
244 type Item = O;
245
246 fn next(&mut self) -> Option<Self::Item> {
247 self.iter
248 .next()
249 .map(|item| (self.map)(item, self.iter.context()))
250 }
251
252 fn size_hint(&self) -> (usize, Option<usize>) {
253 self.iter.size_hint()
254 }
255}
256
257impl<I, O> DoubleEndedIterator for MapCtx<I, O>
258where
259 I: DoubleEndedIterator + ContextIterator,
260{
261 fn next_back(&mut self) -> Option<Self::Item> {
262 self.iter
263 .next_back()
264 .map(|item| (self.map)(item, self.iter.context()))
265 }
266}
267
268impl<I, O> ExactSizeIterator for MapCtx<I, O>
269where
270 I: ExactSizeIterator + ContextIterator,
271{
272 fn len(&self) -> usize {
273 self.iter.len()
274 }
275}
276
277impl<I, O> FusedIterator for MapCtx<I, O> where I: FusedIterator + ContextIterator {}
278
279impl<I, O> ContextIterator for MapCtx<I, O>
280where
281 I: ContextIterator,
282{
283 type Context = I::Context;
284
285 fn context(&self) -> &Self::Context {
286 self.iter.context()
287 }
288}
289
290pub type FilterWithCtx<I, Ctx> = FilterCtx<WithCtx<I, Ctx>>;
293
294#[derive(Clone, Debug)]
299pub struct FilterCtx<I>
300where
301 I: ContextIterator,
302{
303 pub(self) iter: I,
304 pub(self) predicate: fn(&I::Item, &I::Context) -> bool,
305}
306
307impl<I> Iterator for FilterCtx<I>
308where
309 I: ContextIterator,
310{
311 type Item = I::Item;
312
313 #[inline]
314 fn next(&mut self) -> Option<Self::Item> {
315 loop {
318 let item = self.iter.next()?;
319 if (self.predicate)(&item, self.iter.context()) {
320 return Some(item);
321 }
322 }
323 }
324
325 #[inline]
326 fn size_hint(&self) -> (usize, Option<usize>) {
327 (0, self.iter.size_hint().1)
328 }
329
330 #[inline]
331 fn count(mut self) -> usize {
332 let mut sum = 0;
333 while let Some(item) = self.iter.next() {
334 sum += (self.predicate)(&item, self.iter.context()) as usize;
335 }
336 sum
337 }
338}
339
340impl<I> DoubleEndedIterator for FilterCtx<I>
341where
342 I: DoubleEndedIterator + ContextIterator,
343{
344 #[inline]
345 fn next_back(&mut self) -> Option<Self::Item> {
346 loop {
347 let item = self.iter.next_back()?;
348 if (self.predicate)(&item, self.iter.context()) {
349 return Some(item);
350 }
351 }
352 }
353}
354
355impl<I> FusedIterator for FilterCtx<I> where I: FusedIterator + ContextIterator {}
356
357impl<I> ContextIterator for FilterCtx<I>
358where
359 I: ContextIterator,
360{
361 type Context = I::Context;
362
363 #[inline]
364 fn context(&self) -> &Self::Context {
365 self.iter.context()
366 }
367}
368
369pub type FilterMapWithCtx<I, Ctx, O> = FilterMapCtx<WithCtx<I, Ctx>, O>;
372
373#[derive(Clone, Debug)]
378pub struct FilterMapCtx<I, O>
379where
380 I: ContextIterator,
381{
382 pub(self) iter: I,
383 pub(self) predicate: fn(I::Item, &I::Context) -> Option<O>,
384}
385
386impl<I, O> Iterator for FilterMapCtx<I, O>
387where
388 I: ContextIterator,
389{
390 type Item = O;
391
392 #[inline]
393 fn next(&mut self) -> Option<Self::Item> {
394 loop {
397 let item = self.iter.next()?;
398 if let Some(elem) = (self.predicate)(item, self.iter.context()) {
399 return Some(elem);
400 }
401 }
402 }
403
404 #[inline]
405 fn size_hint(&self) -> (usize, Option<usize>) {
406 (0, self.iter.size_hint().1)
407 }
408
409 #[inline]
410 fn count(mut self) -> usize {
411 let mut sum = 0;
412 while let Some(item) = self.iter.next() {
413 sum += (self.predicate)(item, self.iter.context()).is_some() as usize;
414 }
415 sum
416 }
417}
418
419impl<I, O> DoubleEndedIterator for FilterMapCtx<I, O>
420where
421 I: DoubleEndedIterator + ContextIterator,
422{
423 #[inline]
424 fn next_back(&mut self) -> Option<Self::Item> {
425 loop {
426 let item = self.iter.next_back()?;
427 if let Some(elem) = (self.predicate)(item, self.iter.context()) {
428 return Some(elem);
429 }
430 }
431 }
432}
433
434impl<I, O> FusedIterator for FilterMapCtx<I, O> where I: FusedIterator + ContextIterator {}
435
436impl<I, O> ContextIterator for FilterMapCtx<I, O>
437where
438 I: ContextIterator,
439{
440 type Context = I::Context;
441
442 #[inline]
443 fn context(&self) -> &Self::Context {
444 self.iter.context()
445 }
446}
447
448#[cfg(test)]
449mod test {
450 use std::ops::Range;
451
452 use super::*;
453
454 #[test]
455 fn named_map() {
456 type MappedIterator = MapCtx<WithCtx<Range<u16>, u16>, usize>;
457 let iter: MappedIterator = (0..10)
458 .with_context(42)
459 .map_with_context(|item: u16, context: &u16| (item + *context) as usize);
460
461 assert_eq!(iter.context(), &42);
462 assert_eq!(iter.len(), 10);
463 assert!(iter.eq(42..52));
464 }
465
466 #[test]
467 fn filter() {
468 let iter = (0..10)
469 .with_context(42)
470 .filter_with_context(|item: &usize, context: &usize| item + *context >= 50);
471
472 assert_eq!(iter.context(), &42);
473 assert_eq!(iter.clone().count(), 2);
474 assert!(iter.eq(8..10));
475 }
476
477 #[test]
478 fn filter_map() {
479 let iter = (0..10)
480 .with_context(42)
481 .map_with_context(|item: usize, context: &usize| item + *context);
482
483 assert_eq!(iter.context(), &42);
484 assert_eq!(iter.len(), 10);
485 assert!(iter.eq(42..52));
486 }
487}