dioxus_lazy/
factory.rs

1use futures::Future;
2use std::{ops::Range, pin::Pin};
3
4pub trait Factory {
5    type Item;
6    type Output: IntoIterator<Item = Self::Item>;
7    type Future: Future<Output = Self::Output>;
8
9    fn make(&self, range: Range<usize>, is_rev: bool) -> Self::Future;
10}
11
12pub fn from_fn<F, Fut, V>(f: F) -> FromFn<F>
13where
14    F: Fn(usize) -> Fut + Clone + 'static,
15    Fut: Future<Output = V> + 'static,
16    V: 'static,
17{
18    FromFn { f }
19}
20
21#[derive(Clone, Copy)]
22pub struct FromFn<F> {
23    f: F,
24}
25
26impl<F, Fut, V> Factory for FromFn<F>
27where
28    F: Fn(usize) -> Fut + Clone + 'static,
29    Fut: Future<Output = V> + 'static,
30    V: 'static,
31{
32    type Item = V;
33    type Output = std::vec::IntoIter<V>;
34    type Future = Pin<Box<dyn Future<Output = Self::Output>>>;
35
36    fn make(&self, range: Range<usize>, is_rev: bool) -> Self::Future {
37        let f = self.f.clone();
38        Box::pin(async move {
39            let mut values = Vec::new();
40
41            if is_rev {
42                for idx in range.rev() {
43                    values.push(f(idx).await)
44                }
45            } else {
46                for idx in range {
47                    values.push(f(idx).await)
48                }
49            }
50
51            values.into_iter()
52        })
53    }
54}
55
56pub fn from_range_fn<F, Fut, I, V>(f: F) -> FromRangeFn<F>
57where
58    F: Fn(Range<usize>, bool) -> Fut + Clone + 'static,
59    Fut: Future<Output = I> + 'static,
60    I: IntoIterator<Item = V>,
61    V: 'static,
62{
63    FromRangeFn { f }
64}
65
66#[derive(Clone, Copy)]
67pub struct FromRangeFn<F> {
68    f: F,
69}
70
71impl<F, Fut, I, V> Factory for FromRangeFn<F>
72where
73    F: Fn(Range<usize>, bool) -> Fut + Clone + 'static,
74    Fut: Future<Output = I> + 'static,
75    I: IntoIterator<Item = V>,
76    V: 'static,
77{
78    type Item = V;
79    type Output = I;
80    type Future = Pin<Box<dyn Future<Output = Self::Output>>>;
81
82    fn make(&self, input: Range<usize>, is_rev: bool) -> Self::Future {
83        Box::pin((self.f)(input, is_rev))
84    }
85}