Skip to main content

dnet_utils/
void.rs

1//! Transport sending messages into the void, never receiving any messages.
2
3use std::{
4    convert::Infallible,
5    marker::PhantomData,
6    pin::Pin,
7    task::{Context, Poll},
8};
9
10use futures::{stream::FusedStream, Sink, Stream};
11
12/// Transport sending messages into the void, never receiving any messages.
13///
14/// Sending messages into this transport will always succeed.<br>
15/// Attempt to receive message will never complete.
16pub struct Void<Incoming, Outgoing> {
17    #[cfg(feature = "logging")]
18    logger: dnet_base::Logger,
19
20    _incoming: PhantomData<Incoming>,
21    _outgoing: PhantomData<Outgoing>,
22}
23
24impl<Incoming, Outgoing> Default for Void<Incoming, Outgoing> {
25    fn default() -> Self {
26        Self {
27            #[cfg(feature = "logging")]
28            logger: dnet_base::Logger::new::<Self>(),
29
30            _incoming: PhantomData,
31            _outgoing: PhantomData,
32        }
33    }
34}
35
36impl<Incoming, Outgoing> Sink<Outgoing> for Void<Incoming, Outgoing> {
37    type Error = dnet_base::Error<Infallible>;
38
39    fn poll_ready(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
40        let result = Poll::Ready(Ok(()));
41
42        #[cfg(feature = "logging")]
43        self.logger.log_ready(&result);
44
45        result
46    }
47
48    fn start_send(self: Pin<&mut Self>, _item: Outgoing) -> Result<(), Self::Error> {
49        let result = Ok(());
50
51        #[cfg(feature = "logging")]
52        self.logger.log_sending::<Outgoing, _>(&result, None);
53
54        result
55    }
56
57    fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
58        let result = Poll::Ready(Ok(()));
59
60        #[cfg(feature = "logging")]
61        self.logger.log_flush(&result);
62
63        result
64    }
65
66    fn poll_close(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
67        let result = Poll::Ready(Ok(()));
68
69        #[cfg(feature = "logging")]
70        self.logger.log_close(&result);
71
72        result
73    }
74}
75
76impl<Incoming, Outgoing> Stream for Void<Incoming, Outgoing> {
77    type Item = Result<Incoming, Infallible>;
78
79    fn poll_next(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
80        #[cfg(feature = "logging")]
81        self.logger.log_receive_from_void();
82
83        Poll::Pending
84    }
85}
86
87impl<Incoming, Outgoing> FusedStream for Void<Incoming, Outgoing> {
88    fn is_terminated(&self) -> bool {
89        false
90    }
91}
92
93#[cfg(feature = "logging")]
94impl<Incoming, Outgoing> dnet_base::Logging for Void<Incoming, Outgoing> {
95    const KIND: &'static str = "Void";
96
97    fn with_logger<F, R>(&self, f: F) -> R
98    where
99        F: FnOnce(&dnet_base::Logger) -> R,
100    {
101        f(&self.logger)
102    }
103
104    fn with_logger_mut<'a, F, R>(&mut self, f: F) -> R
105    where
106        F: FnOnce(&mut dnet_base::Logger) -> R,
107    {
108        f(&mut self.logger)
109    }
110}
111
112#[cfg(test)]
113mod tests {
114    use core::panic;
115    use std::pin::pin;
116    use std::time::Duration;
117
118    use dnet_base::Receive;
119    use dnet_tests::{dtest, dtest_configure};
120    use dportable::time::sleep;
121    use futures::{select, FutureExt, SinkExt};
122
123    use crate::void::Void;
124
125    dtest_configure!();
126
127    #[dtest]
128    async fn test_void() {
129        let mut void: Void<i32, &str> = Void::default();
130
131        #[cfg(feature = "logging")]
132        {
133            use dnet_base::Logging;
134            dnet_tests::init_subscriber();
135            void.enable_logging();
136        }
137
138        void.send("Hello").await.unwrap();
139
140        let mut delay = pin!(sleep(Duration::from_millis(10)).fuse());
141        let delay_finished_first;
142        select! {
143            _ = delay => {
144                delay_finished_first = true;
145            }
146            _result = void.receive() => {
147                panic!("received message");
148            }
149        }
150        assert!(delay_finished_first);
151    }
152}