moq_net/model/
bandwidth.rs1use std::task::Poll;
10
11use crate::{Error, Result};
12
13#[derive(Default)]
14struct State {
15 bitrate: Option<u64>,
16 abort: Option<Error>,
17}
18
19#[derive(Clone)]
21pub struct Producer {
22 state: kio::Producer<State>,
23}
24
25impl Producer {
26 pub fn new() -> Self {
28 Self {
29 state: kio::Producer::default(),
30 }
31 }
32
33 pub fn set(&self, bitrate: Option<u64>) -> Result<()> {
35 let mut state = self.modify()?;
36 if state.bitrate != bitrate {
37 state.bitrate = bitrate;
38 }
39 Ok(())
40 }
41
42 pub fn consume(&self) -> Consumer {
44 Consumer {
45 state: self.state.consume(),
46 last: None,
47 }
48 }
49
50 pub fn abort(&self, err: Error) -> Result<()> {
52 let mut state = self.modify()?;
53 state.abort = Some(err);
54 state.close();
55 Ok(())
56 }
57
58 pub async fn closed(&self) {
60 self.state.closed().await
61 }
62
63 pub async fn unused(&self) -> Result<()> {
65 kio::wait(|waiter| self.poll_unused(waiter)).await
66 }
67
68 pub fn poll_unused(&self, waiter: &kio::Waiter) -> Poll<Result<()>> {
70 self.state.poll_unused(waiter).map(|used| match used {
71 Some(()) => Ok(()),
72 None => Err(self.close_error()),
73 })
74 }
75
76 pub async fn used(&self) -> Result<()> {
78 kio::wait(|waiter| self.poll_used(waiter)).await
79 }
80
81 pub fn poll_used(&self, waiter: &kio::Waiter) -> Poll<Result<()>> {
83 self.state.poll_used(waiter).map(|used| match used {
84 Some(()) => Ok(()),
85 None => Err(self.close_error()),
86 })
87 }
88
89 fn modify(&self) -> Result<kio::Mut<'_, State>> {
90 self.state
91 .write()
92 .map_err(|r| r.abort.clone().unwrap_or(Error::Dropped))
93 }
94
95 fn close_error(&self) -> Error {
97 self.state.read().abort.clone().unwrap_or(Error::Dropped)
98 }
99}
100
101impl Default for Producer {
102 fn default() -> Self {
103 Self::new()
104 }
105}
106
107#[derive(Clone)]
109pub struct Consumer {
110 state: kio::Consumer<State>,
111 last: Option<u64>,
112}
113
114impl Consumer {
115 pub fn peek(&self) -> Option<u64> {
117 self.state.read().bitrate
118 }
119
120 pub fn poll_changed(&mut self, waiter: &kio::Waiter) -> Poll<Result<Option<u64>>> {
131 let last = self.last;
132
133 match self.state.poll(waiter, |state| {
134 if state.bitrate != last {
135 Poll::Ready(state.bitrate)
136 } else {
137 Poll::Pending
138 }
139 }) {
140 Poll::Ready(Ok(bitrate)) => {
141 self.last = bitrate;
142 Poll::Ready(Ok(bitrate))
143 }
144 Poll::Ready(Err(state)) => Poll::Ready(Err(state.abort.clone().unwrap_or(Error::Dropped))),
149 Poll::Pending => Poll::Pending,
150 }
151 }
152
153 pub async fn changed(&mut self) -> Result<Option<u64>> {
161 kio::wait(|waiter| self.poll_changed(waiter)).await
162 }
163}
164
165#[cfg(test)]
166mod tests {
167 use super::*;
168
169 #[tokio::test]
174 async fn closed_is_distinct_from_unavailable() {
175 let producer = Producer::new();
176 let mut consumer = producer.consume();
177
178 producer.set(Some(1_000_000)).unwrap();
179 assert_eq!(consumer.changed().await.unwrap(), Some(1_000_000));
180
181 producer.set(None).unwrap();
183 assert_eq!(consumer.changed().await.unwrap(), None);
184
185 producer.abort(Error::Cancel).unwrap();
187 assert!(consumer.changed().await.is_err());
188 assert!(consumer.changed().await.is_err());
190 }
191}