1use std::{
13 marker::PhantomData,
14 pin::Pin,
15 task::{Context, Poll},
16};
17
18use futures::{stream::FusedStream, Sink, Stream, StreamExt};
19use pin_project::pin_project;
20
21use super::number::Number;
22
23pub trait OnlyLatest<N, Incoming, Outgoing, Error>:
25 dnet_base::Transport<Incoming, Outgoing, Error> + Sized + Unpin
26where
27 Error: std::error::Error,
28{
29 fn only_latest(self) -> Latest<Self, Error, N, Incoming, Outgoing>
32 where
33 Incoming: Number<Output = N>,
34 for<'a> &'a N: PartialOrd,
35 {
36 Latest::new(self)
37 }
38}
39
40impl<T, N, Incoming, Outgoing, Error> OnlyLatest<N, Incoming, Outgoing, Error> for T
41where
42 T: dnet_base::Transport<Incoming, Outgoing, Error> + Unpin,
43 Error: std::error::Error,
44{
45}
46
47#[pin_project]
53pub struct Latest<T, E, N, Incoming, Outgoing>
54where
55 T: dnet_base::Transport<Incoming, Outgoing, E>,
56 Incoming: Number<Output = N>,
57 for<'a> &'a N: PartialOrd,
58 E: std::error::Error,
59{
60 #[pin]
61 inner: T,
62 last_number: Option<N>,
63
64 #[cfg(feature = "logging")]
65 logger: dnet_base::Logger,
66
67 _error: PhantomData<E>,
68 _incoming: PhantomData<Incoming>,
69 _outgoing: PhantomData<Outgoing>,
70}
71
72impl<T, E, N, Incoming, Outgoing> Latest<T, E, N, Incoming, Outgoing>
73where
74 T: dnet_base::Transport<Incoming, Outgoing, E>,
75 Incoming: Number<Output = N>,
76 for<'a> &'a N: PartialOrd,
77 E: std::error::Error,
78{
79 pub fn new(transport: T) -> Self {
84 Latest {
85 inner: transport,
86 last_number: None,
87
88 #[cfg(feature = "logging")]
89 logger: dnet_base::Logger::new::<Self>(),
90
91 _error: PhantomData,
92 _incoming: PhantomData,
93 _outgoing: PhantomData,
94 }
95 }
96}
97
98impl<T, E, N, Incoming, Outgoing> Sink<Outgoing> for Latest<T, E, N, Incoming, Outgoing>
99where
100 T: dnet_base::Transport<Incoming, Outgoing, E>,
101 Incoming: Number<Output = N>,
102 for<'a> &'a N: PartialOrd,
103 E: std::error::Error,
104{
105 type Error = dnet_base::Error<E>;
106
107 fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
108 let me = self.project();
109 let result = me.inner.poll_ready(cx);
110
111 #[cfg(feature = "logging")]
112 me.logger.log_ready(&result);
113
114 result
115 }
116
117 fn start_send(self: Pin<&mut Self>, item: Outgoing) -> Result<(), Self::Error> {
118 let me = self.project();
119 let result = me.inner.start_send(item);
120
121 #[cfg(feature = "logging")]
122 match &result {
123 Ok(_) => me.logger.log_message_preparation_success::<Outgoing>(None),
124 Err(error) => me.logger.log_sending_failure(error),
125 }
126
127 result
128 }
129
130 fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
131 let me = self.project();
132 let result = me.inner.poll_flush(cx);
133
134 #[cfg(feature = "logging")]
135 me.logger.log_flush(&result);
136
137 result
138 }
139
140 fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
141 let me = self.project();
142 let result = me.inner.poll_close(cx);
143
144 #[cfg(feature = "logging")]
145 me.logger.log_close(&result);
146
147 result
148 }
149}
150
151impl<T, E, N, Incoming, Outgoing> Stream for Latest<T, E, N, Incoming, Outgoing>
152where
153 T: dnet_base::Transport<Incoming, Outgoing, E>,
154 Incoming: Number<Output = N>,
155 for<'a> &'a N: PartialOrd,
156 E: std::error::Error,
157{
158 type Item = Result<Incoming, E>;
159
160 fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
161 let mut me = self.project();
162 let mut latest = None;
163 let result = loop {
164 match me.inner.poll_next_unpin(cx) {
165 Poll::Ready(item) => {
166 if let Some(item) = item {
167 let item = item?;
168 let number = item.number();
169
170 if let Some(last_number) = me.last_number.as_ref() {
171 if &number > last_number {
172 latest = Some(item);
173 *me.last_number = Some(number);
174 }
175
176 #[cfg(feature = "logging")]
177 me.logger.log_incoming_filtered_out::<Incoming>();
178 } else {
179 latest = Some(item);
180 *me.last_number = Some(number);
181 }
182 } else {
183 break Poll::Ready(None);
184 }
185 }
186 Poll::Pending => {
187 break if let Some(latest) = latest {
188 Poll::Ready(Some(Ok(latest)))
189 } else {
190 Poll::Pending
191 }
192 }
193 }
194 };
195
196 #[cfg(feature = "logging")]
197 me.logger.log_receiving(&result, None);
198
199 result
200 }
201}
202
203impl<T, E, N, Incoming, Outgoing> FusedStream for Latest<T, E, N, Incoming, Outgoing>
204where
205 T: dnet_base::Transport<Incoming, Outgoing, E> + FusedStream,
206 Incoming: Number<Output = N>,
207 for<'a> &'a N: PartialOrd,
208 E: std::error::Error,
209{
210 fn is_terminated(&self) -> bool {
211 self.inner.is_terminated()
212 }
213}
214
215#[cfg(feature = "logging")]
216impl<T, E, N, Incoming, Outgoing> dnet_base::Logging for Latest<T, E, N, Incoming, Outgoing>
217where
218 T: dnet_base::Transport<Incoming, Outgoing, E> + dnet_base::Logging,
219 Incoming: Number<Output = N>,
220 for<'a> &'a N: PartialOrd,
221 E: std::error::Error,
222{
223 const KIND: &'static str = "Latest";
224
225 fn with_logger<F, R>(&self, f: F) -> R
226 where
227 F: FnOnce(&dnet_base::Logger) -> R,
228 {
229 f(&self.logger)
230 }
231
232 fn with_logger_mut<F, R>(&mut self, f: F) -> R
233 where
234 F: FnOnce(&mut dnet_base::Logger) -> R,
235 {
236 f(&mut self.logger)
237 }
238}
239
240#[cfg(test)]
241mod tests {
242 use dnet_base::Receive;
243 use dnet_tests::{dtest, dtest_configure};
244 use futures::SinkExt;
245
246 use crate::{
247 channel::transports,
248 latest::OnlyLatest,
249 number::{NumberMessagesU128, NumberMessagesU32, Wrapper},
250 unwrap::{Unwrap, Unwrapping},
251 };
252
253 dtest_configure!();
254
255 #[dtest]
256 async fn test_transport() {
257 let (left, right) = transports();
258
259 let mut left = left.number_messages_u32().only_latest().unwrapping();
260 let mut right = right.number_messages_u32().only_latest().unwrapping();
261
262 dnet_tests::init_logging(&mut left, &mut right);
263
264 left.send(1).await.unwrap();
265 left.send(2).await.unwrap();
266 left.send(3).await.unwrap();
267
268 assert_eq!(right.receive().await.unwrap(), 3);
269
270 right.send(1).await.unwrap();
271 right.send(2).await.unwrap();
272 right.send(3).await.unwrap();
273
274 assert_eq!(left.receive().await.unwrap(), 3);
275 }
276
277 #[dtest]
278 async fn test_order() {
279 let (left, right) = transports();
280
281 let mut left = left.only_latest();
282 let mut right = right.number_messages_u128().only_latest();
283
284 dnet_tests::init_logging(&mut left, &mut right);
285
286 left.send(Wrapper {
287 number: 1,
288 wrapped: 2,
289 })
290 .await
291 .unwrap();
292 left.send(Wrapper {
293 number: 2,
294 wrapped: 3,
295 })
296 .await
297 .unwrap();
298 left.send(Wrapper {
299 number: 0,
300 wrapped: 1,
301 })
302 .await
303 .unwrap();
304
305 right.send(1).await.unwrap();
306
307 assert_eq!(right.receive().await.unwrap().unwrap(), 3);
308 assert_eq!(left.receive().await.unwrap().unwrap(), 1);
309 }
310}