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}