yield_progress/
builder.rs

1use core::future::Future;
2
3use alloc::boxed::Box;
4use alloc::sync::Arc;
5
6use crate::{BoxFuture, ProgressInfo, YieldInfo, YieldProgress, Yielding, basic_yield_now};
7
8/// Builder for creating root [`YieldProgress`] instances.
9///
10/// # Example
11///
12/// ```
13/// # struct Pb;
14/// # impl Pb { fn set_value(&self, _value: f32) {} }
15/// # let some_progress_bar = Pb;
16/// let progress = yield_progress::Builder::new()
17///     .yield_using(|_| tokio::task::yield_now())
18///     .progress_using(move |info| {
19///         some_progress_bar.set_value(info.fraction());
20///     })
21///     .build();
22/// ```
23#[derive(Clone)]
24#[must_use]
25pub struct Builder {
26    yielding: Arc<Yielding<crate::YieldFn>>,
27    /// public to allow overriding the API `Sync` requirement
28    pub(crate) progressor: Arc<crate::ProgressFn>,
29}
30
31impl Builder {
32    /// Constructs a [`Builder`].
33    ///
34    /// The default values are:
35    ///
36    /// * The yield function is [`basic_yield_now`].
37    /// * The progress function does nothing.
38    ///
39    /// The call site of this function is considered to be the yield point preceding the first actual
40    /// yield point.
41    #[track_caller]
42    pub fn new() -> Builder {
43        Builder {
44            yielding: Arc::new(Yielding {
45                yielder: move |_info: &YieldInfo<'_>| -> BoxFuture<'static, ()> {
46                    Box::pin(basic_yield_now())
47                },
48                #[cfg(feature = "log_hiccups")]
49                state: std::sync::Mutex::new(crate::YieldState {
50                    last_finished_yielding: web_time::Instant::now(),
51                    last_yield_location: core::panic::Location::caller(),
52                    last_yield_label: None,
53                }),
54            }),
55            progressor: Arc::new(|_| {}),
56        }
57    }
58
59    /// Construct a new [`YieldProgress`] using the behaviors specified by this builder.
60    pub fn build(self) -> YieldProgress {
61        let Self {
62            yielding,
63            progressor,
64        } = self;
65
66        YieldProgress {
67            start: 0.0,
68            end: 1.0,
69            label: None,
70            yielding,
71            progressor,
72        }
73    }
74
75    /// Set the function which will be called in order to yield.
76    ///
77    /// See [`basic_yield_now()`] for the default implementation used if this is not not set, and
78    /// some information about what you might want to pass here instead.
79    #[allow(clippy::missing_panics_doc)] // internal, can't happen
80    pub fn yield_using<Y, YFut>(mut self, function: Y) -> Self
81    where
82        Y: for<'a> Fn(&'a YieldInfo<'a>) -> YFut + Send + Sync + 'static,
83        YFut: Future<Output = ()> + Send + 'static,
84    {
85        let new_yielding = Arc::new(Yielding {
86            yielder: move |info: &YieldInfo<'_>| -> BoxFuture<'static, ()> {
87                Box::pin(function(info))
88            },
89            #[cfg(feature = "log_hiccups")]
90            state: std::sync::Mutex::new(self.yielding.state.lock().unwrap().clone()),
91        });
92        self.yielding = new_yielding;
93        self
94    }
95
96    /// Internal version of `yield_using` which takes an already boxed function and yielding state.
97    #[cfg_attr(not(feature = "sync"), allow(dead_code))]
98    pub(crate) fn yielding_internal(mut self, new_yielding: crate::BoxYielding) -> Self {
99        self.yielding = new_yielding;
100        self
101    }
102
103    /// Set the function which will be called in order to report progress.
104    ///
105    /// If this is called more than once, the previous function will be discarded (there is no list
106    /// of callbacks). If this is not called, the default function used does nothing.
107    pub fn progress_using<P>(mut self, function: P) -> Self
108    where
109        P: for<'a> Fn(&'a ProgressInfo<'a>) + Send + Sync + 'static,
110    {
111        self.progressor = Arc::new(function);
112        self
113    }
114}
115
116impl Default for Builder {
117    fn default() -> Self {
118        Self::new()
119    }
120}