ad_hoc_iterator/
lib.rs

1#![no_std]
2
3//! # Ad hoc Iterator
4//!
5//! This is a very small crate providing a macro and a function that allow for
6//! conveniently creating iterators on the fly.
7//! 
8//! With the [`iterate`](iterate) macro of this crate, you can however do
9//! exactly that. See it's documentation for more information.
10//!
11//! With the [`iterator_from`](iterator_from) function, you can directly create
12//! an iterator from an `FnMut` closure (which is exactly the same as what the
13//! `iterate` macro is doing behind the scenes).
14
15/// Internal, not intended for direct use.
16///
17/// See [`iterate`](iterate) & [`iterator_from`](iterator_from).
18#[doc(hidden)]
19pub struct __ClosureIterator<F>(pub Option<F>);
20
21impl<T, F: FnMut() -> Option<T>> Iterator for __ClosureIterator<F> {
22    type Item = T;
23
24    fn next(&mut self) -> Option<Self::Item> {
25        let r = self.0.as_mut().and_then(|f| f());
26        if r.is_none() {
27            self.0 = None;
28            None
29        } else {
30            r
31        }
32    }
33}
34
35/// Internal, not intended for direct use.
36///
37/// See [`iterate`](iterate) & [`iterator_from`](iterator_from).
38#[doc(hidden)]
39#[macro_export]
40macro_rules! __iterate {
41    ($b:block) => {
42        ::ad_hoc_iterator::iterator_from(move || $b)
43    };
44}
45
46/// Create an ad hoc iterator.
47///
48/// # Usage
49///
50/// The macro is used just like defining a closure. The return type of it's body
51/// has to be `Option<T>` for some type T. So at the minimum: `iterate!{ None }`
52///
53/// The expression `iterate! {...}` is of type `impl Iterator<T>`.
54///
55/// Any captured variables are moved (like with `move || {...}` closures).
56///
57/// You can use `return` statements in the body of `iterate!`.
58///
59/// # Example
60///
61/// ```
62/// use ad_hoc_iterator::iterate;
63///
64/// fn count_to(n: usize) -> impl Iterator<Item = usize> {
65///     let mut i = 0;
66///     iterate! {
67///         if i < n {
68///             i += 1;
69///             Some(i-1)
70///         } else {
71///             None
72///         }
73///     }
74/// }
75/// ```
76#[macro_export]
77macro_rules! iterate {
78    ($( $ts:tt )*) => {
79        ::ad_hoc_iterator::__iterate!{{ $($ts)* }}
80    };
81}
82
83/// Turn a closure into an iterator.
84///
85/// Each `next()` on the iterator will simply call the closure once. The
86/// iterator ends when the closure returns `None`. The closure will not be
87/// called again after that point, even if `next()` is called again.
88///
89/// # Example
90///
91/// ```
92/// use ad_hoc_iterator::iterator_from;
93///
94/// fn count_from_to(n: usize, m: usize) -> impl Iterator<Item = usize> {
95///     let mut i = n;
96///     iterator_from(move || {
97///         if i < m {
98///             i += 1;
99///             Some(i - 1)
100///         } else {
101///             None
102///         }
103///     })
104/// }
105/// ```
106#[inline(always)]
107pub fn iterator_from<T, F: FnMut() -> Option<T>>(f: F) -> impl Iterator<Item = T> {
108    __ClosureIterator(Some(f))
109}