Skip to main content

zest_core/
time.rs

1//! Time-based subscription primitives.
2//!
3//! [`every`] is the common case — fire a message every N. It wraps the
4//! built-in [`Tick`] recipe so users don't have to define their own.
5
6use crate::application::{BoxFuture, Recipe, Subscription};
7use alloc::boxed::Box;
8use core::hash::{Hash, Hasher};
9use embassy_time::{Duration, Timer};
10
11/// Periodic-tick [`Recipe`]: emit `message.clone()` every `duration`.
12///
13/// Identity = `TypeId::of::<Tick<M>>()` ⊕ `Hash` of `duration` and
14/// `message`, so two ticks with different durations or different
15/// messages are distinct subscriptions.
16///
17/// Users usually call [`every`] rather than constructing this
18/// directly.
19pub struct Tick<M>
20where
21    M: Clone + 'static,
22{
23    /// Tick period.
24    pub duration: Duration,
25    /// Message to emit on each tick.
26    pub message: M,
27}
28
29impl<M> Hash for Tick<M>
30where
31    M: Clone + Hash + 'static,
32{
33    fn hash<H: Hasher>(&self, state: &mut H) {
34        self.duration.as_ticks().hash(state);
35        self.message.hash(state);
36    }
37}
38
39impl<M> Recipe for Tick<M>
40where
41    M: Clone + Hash + 'static,
42{
43    type Message = M;
44
45    fn next(&mut self) -> Option<BoxFuture<M>> {
46        let duration = self.duration;
47        let message = self.message.clone();
48        Some(Box::pin(async move {
49            Timer::after(duration).await;
50            message
51        }))
52    }
53}
54
55/// Emit `message` every `duration`.
56///
57/// Equivalent to `Subscription::from_recipe(Tick { duration, message })`.
58///
59/// ```ignore
60/// fn subscription(&self) -> Subscription<Msg> {
61///     if self.auto {
62///         zest_core::time::every(Duration::from_secs(1), Msg::Tick)
63///     } else {
64///         Subscription::none()
65///     }
66/// }
67/// ```
68#[must_use]
69pub fn every<M>(duration: Duration, message: M) -> Subscription<M>
70where
71    M: Clone + Hash + 'static,
72{
73    Subscription::from_recipe(Tick { duration, message })
74}