1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
use core::marker::PhantomData;
use super::*;
/// An iterator returned by [`from_fn`].
pub struct FromFn<F, R> {
f: F,
_marker: PhantomData<fn() -> R>,
}
/// A helper type used in [`from_fn`].
///
/// It represents a value that the iterator is stopped with, which `from_fn`
/// closure needs to pass back to the caller. It has a lifetime parameter to
/// prevent values from different scopes from getting mixed up (i.e. if
/// `from_fn` is used within another `from_fn`).
pub struct BreakValue<'a> {
_invariant: PhantomData<fn(&'a ()) -> &'a ()>,
}
impl<F, R> InternalIterator for FromFn<F, R>
where
F: for<'a> FnOnce(&mut dyn FnMut(R) -> ControlFlow<BreakValue<'a>>) -> ControlFlow<BreakValue<'a>>,
{
type Item = R;
fn try_for_each<RR, FF>(self, mut f: FF) -> ControlFlow<RR>
where
FF: FnMut(Self::Item) -> ControlFlow<RR>,
{
let mut result = ControlFlow::Continue(());
(self.f)(&mut |item| {
match f(item) {
ControlFlow::Continue(()) => ControlFlow::Continue(()),
ControlFlow::Break(res) => {
result = ControlFlow::Break(res);
ControlFlow::Break(BreakValue { _invariant: PhantomData })
}
}
});
result
}
}
/// Creates an internal iterator from provided closure.
///
/// Provided closure should be equivalent to how
/// [`InternalIterator::try_for_each`] would be implemented - it should call its
/// parameter with every value that needs to be yielded from the iterator,
/// respect returned `ControlFlow` value, and return
/// `ControlFlow::Continue(())` at the end. Type signature ensures most of
/// that, you only need to take care to use `?` operator on every call when
/// yielding values.
///
/// If you want to construct an [`InternalIterator`] from a closure that yields
/// items one by one, like you would with [`std::iter::from_fn`], then you can
/// use that function with a conversion to internal iterator:
/// `std::iter::from_fn(f).into_internal()`.
///
/// ```
/// # use internal_iterator::InternalIterator;
/// # use std::ops::ControlFlow;
/// let x = 2;
/// let y = Some(3);
///
/// let iter = internal_iterator::from_fn(|f| {
/// f(1)?;
/// f(x)?;
/// if let Some(value) = y {
/// f(value)?;
/// }
/// ControlFlow::Continue(())
/// });
///
/// let values = iter.collect::<Vec<_>>();
/// assert_eq!(values, [1, 2, 3])
/// ```
///
/// Note that [`InternalIterator::try_for_each`] function is generic, but
/// generic closures are not possible. Therefore this function utilizes dynamic
/// dispatch (to be able to provide any function to the closure), and a marker
/// type for break value with the actual value passed via a side channel
/// (to be able to use any type as break value). Because of this, iterators
/// constructed by [`from_fn`] might be optimized more poorly. If the need
/// arises such iterators can always be rewritten as explicit structs with
/// generic implementations of [`InternalIterator::try_for_each`], although that
/// will require manually handling captured variables (whereas compiler does
/// that for you when using closures).
pub fn from_fn<F, R>(f: F) -> FromFn<F, R>
where
F: for<'a> FnOnce(&mut dyn FnMut(R) -> ControlFlow<BreakValue<'a>>) -> ControlFlow<BreakValue<'a>>,
{
FromFn { f, _marker: PhantomData }
}
#[test]
fn pipeline_tests() {
fn check(iter: impl InternalIterator<Item = i32>, expect: &[i32]) {
assert_eq!(iter.collect::<Vec<_>>(), expect);
}
fn make_iter() -> impl InternalIterator<Item = i32> {
from_fn(|f| {
f(1)?;
f(2)?;
f(3)?;
f(4)?;
ControlFlow::Continue(())
})
}
check(make_iter(), &[1, 2, 3, 4]);
check(make_iter().map(|x| x * 2), &[2, 4, 6, 8]);
check(make_iter().filter(|&x| x > 2), &[3, 4]);
check(make_iter().filter(|&x| x <= 2), &[1, 2]);
check(make_iter().chain([7, 8, 9]), &[1, 2, 3, 4, 7, 8, 9]);
}
#[test]
fn can_be_static() {
fn use_static_iterator(iter: impl InternalIterator<Item = i32> + 'static) {
assert_eq!(iter.collect::<Vec<_>>(), &[1, 2, 3]);
}
let mut a = 1;
let iter = from_fn(move |f| {
f(a)?;
a += 1;
f(a)?;
a += 1;
f(a)?;
ControlFlow::Continue(())
});
use_static_iterator(iter);
}
/// ```compile_fail
/// use std::ops::ControlFlow;
/// use internal_iterator::InternalIterator;
///
/// internal_iterator::from_fn(|f| {
/// f(1)?;
/// let mut slot = ControlFlow::Continue(());
/// internal_iterator::from_fn(|f2| {
/// slot = f2(42); // this assignment is supposed to fail to compile,
/// // BreakValue can be moved between from_fn invocations
/// ControlFlow::Continue(())
/// }).collect::<Vec<_>>();
/// slot
/// });
/// ```
fn __compile_fail_check() {}