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