Skip to main content

state_m/
reader.rs

1use crate::{
2    AsState,
3    source::Inner,
4    state::{State, StateEvent},
5};
6use std::{fmt::Debug, ops::Deref};
7use tokio::{
8    select,
9    sync::broadcast::{Sender, channel, error::RecvError},
10};
11
12/// Reader of state, to receive state change events.
13#[derive(Clone, Debug)]
14pub struct Reader<S>(Inner<S>)
15where
16    S: 'static + AsState;
17
18impl<S> Deref for Reader<S>
19where
20    S: 'static + AsState,
21{
22    type Target = Inner<S>;
23
24    fn deref(&self) -> &Self::Target {
25        &self.0
26    }
27}
28
29impl<S> Reader<S>
30where
31    S: 'static + AsState,
32{
33    pub(crate) fn from(inner: Inner<S>) -> Self {
34        Self(inner)
35    }
36
37    pub(crate) fn new(capacity: usize, sender: Sender<StateEvent<S>>) -> Self {
38        Self(Inner {
39            capacity,
40            sender,
41            pass_checks: Default::default(),
42        })
43    }
44}
45
46impl<S> Reader<S>
47where
48    S: 'static + AsState + Send,
49{
50    /// Check is the channel has been closed.
51    pub fn is_closed(&self) -> bool {
52        self.sender.subscribe().is_closed()
53    }
54
55    /// Convert data type of state reader.
56    /// # Arguments
57    /// * `capacity` - capacity of the new broadcast channel will be created.
58    /// # Returns
59    /// Reader of new data type.
60    pub fn extend<T>(&self, capacity: usize) -> Reader<T>
61    where
62        T: AsState + From<S> + Send,
63    {
64        self.extend_with(capacity, T::from)
65    }
66
67    /// Convert data type of state reader, with an closure.
68    /// # Arguments
69    /// * `capacity` - capacity of the new broadcast channel will be created.
70    /// * `f` - an closure, which takes the old state value as parameter, and return the new state value.
71    /// # Returns
72    /// Reader of new data type.
73    pub fn extend_with<T, F>(&self, capacity: usize, f: F) -> Reader<T>
74    where
75        T: AsState + Send,
76        F: Fn(S) -> T + Send + 'static,
77    {
78        let (tx, _) = channel(capacity);
79        let tx_c = tx.clone();
80        let mut rx_o = self.sender.subscribe();
81        tokio::spawn(async move {
82            loop {
83                select! {
84                    res = rx_o.recv() => {
85                        match res {
86                            Ok(s) => {
87                                tracing::trace!("recv -- {:?}", s.state);
88                                let s_new = StateEvent {
89                                    state: State {
90                                        value: f(s.state.value),
91                                        timestamp: s.state.timestamp,
92                                    },
93                                    is_touch: s.is_touch,
94                                    close_handle: s.close_handle,
95                                };
96                                if tx_c.send(s_new).is_err() {
97                                    break;
98                                }
99                            },
100                            Err(e) => {
101                                match e {
102                                    RecvError::Closed => break,
103                                    RecvError::Lagged(n) => {
104                                        tracing::warn!("lagged | skipped {n} messages.")
105                                    },
106                                }
107                            },
108                        }
109                    }
110                }
111            }
112        });
113        Reader(Inner {
114            capacity: self.capacity,
115            sender: tx,
116            pass_checks: self.pass_checks.clone(),
117        })
118    }
119
120    /// Convert data type of state reader, with an async closure.
121    /// # Arguments
122    /// * `capacity` - capacity of the new broadcast channel will be created.
123    /// * `f` - an async closure, which takes the old state value as parameter, and return the new state value.
124    /// # Returns
125    /// Reader of new data type.
126    pub fn async_entend_with<T, F, Fut>(&self, capacity: usize, f: F) -> Reader<T>
127    where
128        T: 'static + AsState + Send,
129        F: Fn(S) -> Fut + Send + Sync + 'static,
130        Fut: Future<Output = T> + Send,
131    {
132        let (tx, _) = channel(capacity);
133        let tx_c = tx.clone();
134        let mut rx_o = self.sender.subscribe();
135        tokio::spawn(async move {
136            loop {
137                select! {
138                    res = rx_o.recv() => {
139                        match res {
140                            Ok(s) => {
141                                tracing::trace!("recv -- {:?}", s.state);
142                                let s_new = StateEvent {
143                                    state: State {
144                                        value: f(s.state.value).await,
145                                        timestamp: s.state.timestamp,
146                                    },
147                                    is_touch: s.is_touch,
148                                    close_handle: s.close_handle,
149                                };
150                                if tx_c.send(s_new).is_err() {
151                                    break;
152                                }
153                            },
154                            Err(e) => {
155                                match e {
156                                    RecvError::Closed => break,
157                                    RecvError::Lagged(n) => {
158                                        tracing::warn!("lagged | skipped {n} messages.")
159                                    },
160                                }
161                            },
162                        }
163                    }
164                }
165            }
166        });
167        Reader(Inner {
168            capacity,
169            sender: tx,
170            pass_checks: self.pass_checks.clone(),
171        })
172    }
173}