1use std::pin::Pin;
4use std::task::{Context, Poll};
5use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
6use tokio::sync::mpsc::{UnboundedReceiver, UnboundedSender};
7
8pub(crate) enum WriteCommand {
9 Data { stream_id: u64, offset: u64, data: Vec<u8>, fin: bool },
10}
11
12pub struct SendStream {
14 tx: Option<UnboundedSender<Option<Vec<u8>>>>,
15 network_tx: Option<UnboundedSender<WriteCommand>>,
16 stream_id: u64,
17 offset: u64,
18}
19
20impl SendStream {
21 pub(crate) fn pair() -> (Self, RecvStream) {
22 let (tx, rx) = tokio::sync::mpsc::unbounded_channel();
23 (
24 Self { tx: Some(tx), network_tx: None, stream_id: 0, offset: 0 },
25 RecvStream {
26 rx,
27 pending: None,
28 offset: 0,
29 },
30 )
31 }
32
33 pub(crate) fn network(tx: UnboundedSender<WriteCommand>, stream_id: u64) -> Self {
34 Self { tx: None, network_tx: Some(tx), stream_id, offset: 0 }
35 }
36}
37
38impl AsyncWrite for SendStream {
39 fn poll_write(
40 self: Pin<&mut Self>,
41 _cx: &mut Context<'_>,
42 buf: &[u8],
43 ) -> Poll<std::io::Result<usize>> {
44 let this = self.get_mut();
45 if let Some(tx) = this.network_tx.as_ref() {
46 let offset = this.offset;
47 tx.send(WriteCommand::Data { stream_id: this.stream_id, offset, data: buf.to_vec(), fin: false })
48 .map_err(|_| std::io::Error::new(std::io::ErrorKind::BrokenPipe, "connection closed"))?;
49 this.offset += buf.len() as u64;
50 return Poll::Ready(Ok(buf.len()));
51 }
52 let tx = this.tx.as_ref().ok_or_else(|| {
53 std::io::Error::new(std::io::ErrorKind::BrokenPipe, "stream is finished")
54 });
55 let tx = match tx {
56 Ok(tx) => tx,
57 Err(err) => return Poll::Ready(Err(err)),
58 };
59 tx.send(Some(buf.to_vec()))
60 .map_err(|_| std::io::Error::new(std::io::ErrorKind::BrokenPipe, "peer closed"))?;
61 Poll::Ready(Ok(buf.len()))
62 }
63
64 fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
65 Poll::Ready(Ok(()))
66 }
67
68 fn poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
69 let this = self.get_mut();
70 if let Some(tx) = this.network_tx.take() {
71 let _ = tx.send(WriteCommand::Data { stream_id: this.stream_id, offset: this.offset, data: Vec::new(), fin: true });
72 return Poll::Ready(Ok(()));
73 }
74 if let Some(tx) = this.tx.take() {
75 let _ = tx.send(None);
76 }
77 Poll::Ready(Ok(()))
78 }
79}
80
81pub struct RecvStream {
83 rx: UnboundedReceiver<Option<Vec<u8>>>,
84 pending: Option<Vec<u8>>,
85 offset: usize,
86}
87
88impl RecvStream {
89 pub(crate) fn from_receiver(rx: UnboundedReceiver<Option<Vec<u8>>>) -> Self {
90 Self { rx, pending: None, offset: 0 }
91 }
92}
93
94impl AsyncRead for RecvStream {
95 fn poll_read(
96 mut self: Pin<&mut Self>,
97 cx: &mut Context<'_>,
98 buf: &mut ReadBuf<'_>,
99 ) -> Poll<std::io::Result<()>> {
100 loop {
101 if let Some(data) = self.pending.as_ref() {
102 let remaining = &data[self.offset..];
103 if remaining.is_empty() {
104 self.pending = None;
105 self.offset = 0;
106 continue;
107 }
108 let n = remaining.len().min(buf.remaining());
109 buf.put_slice(&remaining[..n]);
110 self.offset += n;
111 return Poll::Ready(Ok(()));
112 }
113 match Pin::new(&mut self.rx).poll_recv(cx) {
114 Poll::Ready(Some(Some(data))) => {
115 self.pending = Some(data);
116 }
117 Poll::Ready(Some(None)) | Poll::Ready(None) => return Poll::Ready(Ok(())),
118 Poll::Pending => return Poll::Pending,
119 }
120 }
121 }
122}