1 use crate::Stream;
2 use pin_project_lite::pin_project;
3 use std::io;
4 use std::pin::Pin;
5 use std::task::{Context, Poll};
6 use tokio::io::{AsyncBufRead, Split};
7 
8 pin_project! {
9     /// A wrapper around [`tokio::io::Split`] that implements [`Stream`].
10     ///
11     /// [`tokio::io::Split`]: struct@tokio::io::Split
12     /// [`Stream`]: trait@crate::Stream
13     #[derive(Debug)]
14     #[cfg_attr(docsrs, doc(cfg(feature = "io-util")))]
15     pub struct SplitStream<R> {
16         #[pin]
17         inner: Split<R>,
18     }
19 }
20 
21 impl<R> SplitStream<R> {
22     /// Create a new `SplitStream`.
new(split: Split<R>) -> Self23     pub fn new(split: Split<R>) -> Self {
24         Self { inner: split }
25     }
26 
27     /// Get back the inner `Split`.
into_inner(self) -> Split<R>28     pub fn into_inner(self) -> Split<R> {
29         self.inner
30     }
31 
32     /// Obtain a pinned reference to the inner `Split<R>`.
as_pin_mut(self: Pin<&mut Self>) -> Pin<&mut Split<R>>33     pub fn as_pin_mut(self: Pin<&mut Self>) -> Pin<&mut Split<R>> {
34         self.project().inner
35     }
36 }
37 
38 impl<R: AsyncBufRead> Stream for SplitStream<R> {
39     type Item = io::Result<Vec<u8>>;
40 
poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>>41     fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
42         self.project()
43             .inner
44             .poll_next_segment(cx)
45             .map(Result::transpose)
46     }
47 }
48 
49 impl<R> AsRef<Split<R>> for SplitStream<R> {
as_ref(&self) -> &Split<R>50     fn as_ref(&self) -> &Split<R> {
51         &self.inner
52     }
53 }
54 
55 impl<R> AsMut<Split<R>> for SplitStream<R> {
as_mut(&mut self) -> &mut Split<R>56     fn as_mut(&mut self) -> &mut Split<R> {
57         &mut self.inner
58     }
59 }
60