1use std::{
4 convert::Infallible,
5 marker::PhantomData,
6 pin::Pin,
7 task::{Context, Poll},
8};
9
10use futures::{stream::FusedStream, Sink, Stream};
11
12pub 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}