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