s2n_quic_core/transmission/
interest.rs1use crate::transmission::Constraint;
5
6#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
7pub enum Interest {
8 None,
9 NewData,
10 LostData,
11 Forced,
12}
13
14impl Default for Interest {
15 #[inline]
16 fn default() -> Self {
17 Self::None
18 }
19}
20
21impl Interest {
22 #[inline]
23 pub fn can_transmit(self, limit: Constraint) -> bool {
24 match (self, limit) {
25 (_, Constraint::AmplificationLimited) => false,
27
28 (Interest::Forced, _) => true,
30
31 (Interest::LostData, _) => limit.can_retransmit(),
34
35 (Interest::NewData, _) => limit.can_transmit(),
37
38 (Interest::None, _) => false,
40 }
41 }
42
43 #[inline]
44 pub fn is_none(self) -> bool {
45 matches!(self, Interest::None)
46 }
47
48 #[inline]
49 pub fn merge_with<F: FnOnce(&mut Self) -> Result>(&mut self, f: F) -> Result {
50 f(self)
51 }
52}
53
54pub trait Provider {
55 fn transmission_interest<Q: Query>(&self, query: &mut Q) -> Result;
56
57 #[inline]
58 fn get_transmission_interest(&self) -> Interest {
59 let mut interest = Interest::None;
60 let _ = self.transmission_interest(&mut interest);
61 interest
62 }
63
64 #[inline]
65 fn has_transmission_interest(&self) -> bool {
66 let mut query = HasTransmissionInterestQuery;
67 self.transmission_interest(&mut query).is_err()
68 }
69
70 #[inline]
71 fn can_transmit(&self, mut constraint: Constraint) -> bool {
72 self.transmission_interest(&mut constraint).is_err()
73 }
74}
75
76pub trait Query {
77 fn on_interest(&mut self, interest: Interest) -> Result;
78
79 #[inline]
80 fn on_new_data(&mut self) -> Result {
81 self.on_interest(Interest::NewData)
82 }
83
84 #[inline]
85 fn on_lost_data(&mut self) -> Result {
86 self.on_interest(Interest::LostData)
87 }
88
89 #[inline]
90 fn on_forced(&mut self) -> Result {
91 self.on_interest(Interest::Forced)
92 }
93}
94
95impl Query for Interest {
96 #[inline]
97 fn on_interest(&mut self, interest: Interest) -> Result {
98 match (*self, interest) {
99 (Interest::Forced, _) | (_, Interest::Forced) => {
101 *self = Interest::Forced;
102 return Err(QueryBreak);
103 }
104 (Interest::LostData, _) | (_, Interest::LostData) => *self = Interest::LostData,
105 (Interest::NewData, _) | (_, Interest::NewData) => *self = Interest::NewData,
106 (Interest::None, _) => {}
107 }
108
109 Ok(())
110 }
111}
112
113impl Query for Constraint {
114 #[inline]
115 fn on_interest(&mut self, interest: Interest) -> Result {
116 if interest.can_transmit(*self) {
118 return Err(QueryBreak);
119 }
120
121 Ok(())
122 }
123}
124
125pub struct HasTransmissionInterestQuery;
126
127impl Query for HasTransmissionInterestQuery {
128 #[inline]
129 fn on_interest(&mut self, interest: Interest) -> Result {
130 if interest.is_none() {
131 Ok(())
132 } else {
133 Err(QueryBreak)
135 }
136 }
137
138 #[inline]
140 fn on_new_data(&mut self) -> Result {
141 Err(QueryBreak)
142 }
143
144 #[inline]
145 fn on_lost_data(&mut self) -> Result {
146 Err(QueryBreak)
147 }
148
149 #[inline]
150 fn on_forced(&mut self) -> Result {
151 Err(QueryBreak)
152 }
153}
154
155#[cfg(feature = "std")]
156pub struct Debugger;
157
158#[cfg(feature = "std")]
159impl Query for Debugger {
160 #[inline]
161 #[track_caller]
162 fn on_interest(&mut self, interest: Interest) -> Result {
163 eprintln!(" {} - {:?}", core::panic::Location::caller(), interest);
164 Ok(())
165 }
166
167 #[inline]
168 #[track_caller]
169 fn on_new_data(&mut self) -> Result {
170 eprintln!(
171 " {} - {:?}",
172 core::panic::Location::caller(),
173 Interest::NewData
174 );
175 Ok(())
176 }
177
178 #[inline]
179 #[track_caller]
180 fn on_lost_data(&mut self) -> Result {
181 eprintln!(
182 " {} - {:?}",
183 core::panic::Location::caller(),
184 Interest::LostData
185 );
186 Ok(())
187 }
188
189 #[inline]
190 #[track_caller]
191 fn on_forced(&mut self) -> Result {
192 eprintln!(
193 " {} - {:?}",
194 core::panic::Location::caller(),
195 Interest::Forced
196 );
197 Ok(())
198 }
199}
200
201pub struct QueryBreak;
202
203pub type Result<T = (), E = QueryBreak> = core::result::Result<T, E>;
204
205#[cfg(test)]
206mod test {
207 use crate::transmission::{
208 interest::Query,
209 Constraint,
210 Constraint::*,
211 Interest::{None, *},
212 };
213
214 #[test]
215 fn ordering_test() {
216 assert!(None < NewData);
217 assert!(NewData < LostData);
218 assert!(LostData < Forced);
219 }
220
221 #[test]
222 fn interest_query_test() {
223 let levels = [None, NewData, LostData, Forced];
224 for a in levels.iter().copied() {
225 for b in levels.iter().copied() {
226 let mut query = a;
227 let result = query.on_interest(b);
228
229 assert_eq!(query, a.max(b));
230 assert_eq!(matches!(a, Forced) || matches!(b, Forced), result.is_err());
231 }
232 }
233 }
234
235 #[test]
236 fn can_transmit() {
237 assert!(!None.can_transmit(AmplificationLimited));
239 assert!(!NewData.can_transmit(AmplificationLimited));
240 assert!(!LostData.can_transmit(AmplificationLimited));
241 assert!(!Forced.can_transmit(AmplificationLimited));
242
243 assert!(!None.can_transmit(CongestionLimited));
245 assert!(!NewData.can_transmit(CongestionLimited));
246 assert!(!LostData.can_transmit(CongestionLimited));
247 assert!(Forced.can_transmit(CongestionLimited));
248
249 assert!(!None.can_transmit(RetransmissionOnly));
251 assert!(!NewData.can_transmit(RetransmissionOnly));
252 assert!(LostData.can_transmit(RetransmissionOnly));
253 assert!(Forced.can_transmit(RetransmissionOnly));
254
255 assert!(!None.can_transmit(Constraint::None));
257 assert!(NewData.can_transmit(Constraint::None));
258 assert!(LostData.can_transmit(Constraint::None));
259 assert!(Forced.can_transmit(Constraint::None));
260 }
261}