-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
io: add
AsyncReadExt::read_buf
(#3003)
Brings back `read_buf` from 0.2. This will be stabilized as part of 1.0.
- Loading branch information
1 parent
7fbfa9b
commit 8dbc3c7
Showing
10 changed files
with
392 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
use crate::io::AsyncRead; | ||
|
||
use bytes::BufMut; | ||
use pin_project_lite::pin_project; | ||
use std::future::Future; | ||
use std::io; | ||
use std::marker::PhantomPinned; | ||
use std::pin::Pin; | ||
use std::task::{Context, Poll}; | ||
|
||
pub(crate) fn read_buf<'a, R, B>(reader: &'a mut R, buf: &'a mut B) -> ReadBuf<'a, R, B> | ||
where | ||
R: AsyncRead + Unpin, | ||
B: BufMut, | ||
{ | ||
ReadBuf { | ||
reader, | ||
buf, | ||
_pin: PhantomPinned, | ||
} | ||
} | ||
|
||
pin_project! { | ||
/// Future returned by [`read_buf`](crate::io::AsyncReadExt::read_buf). | ||
#[derive(Debug)] | ||
#[must_use = "futures do nothing unless you `.await` or poll them"] | ||
pub struct ReadBuf<'a, R, B> { | ||
reader: &'a mut R, | ||
buf: &'a mut B, | ||
#[pin] | ||
_pin: PhantomPinned, | ||
} | ||
} | ||
|
||
impl<R, B> Future for ReadBuf<'_, R, B> | ||
where | ||
R: AsyncRead + Unpin, | ||
B: BufMut, | ||
{ | ||
type Output = io::Result<usize>; | ||
|
||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<usize>> { | ||
use crate::io::ReadBuf; | ||
use std::mem::MaybeUninit; | ||
|
||
let me = self.project(); | ||
|
||
if !me.buf.has_remaining_mut() { | ||
return Poll::Ready(Ok(0)); | ||
} | ||
|
||
let n = { | ||
let dst = me.buf.bytes_mut(); | ||
let dst = unsafe { &mut *(dst as *mut _ as *mut [MaybeUninit<u8>]) }; | ||
let mut buf = ReadBuf::uninit(dst); | ||
let ptr = buf.filled().as_ptr(); | ||
ready!(Pin::new(me.reader).poll_read(cx, &mut buf)?); | ||
|
||
// Ensure the pointer does not change from under us | ||
assert_eq!(ptr, buf.filled().as_ptr()); | ||
buf.filled().len() | ||
}; | ||
|
||
// Safety: This is guaranteed to be the number of initialized (and read) | ||
// bytes due to the invariants provided by `ReadBuf::filled`. | ||
unsafe { | ||
me.buf.advance_mut(n); | ||
} | ||
|
||
Poll::Ready(Ok(n)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
use crate::io::AsyncWrite; | ||
|
||
use bytes::Buf; | ||
use pin_project_lite::pin_project; | ||
use std::future::Future; | ||
use std::io; | ||
use std::marker::PhantomPinned; | ||
use std::pin::Pin; | ||
use std::task::{Context, Poll}; | ||
|
||
pin_project! { | ||
/// A future to write some of the buffer to an `AsyncWrite`. | ||
#[derive(Debug)] | ||
#[must_use = "futures do nothing unless you `.await` or poll them"] | ||
pub struct WriteBuf<'a, W, B> { | ||
writer: &'a mut W, | ||
buf: &'a mut B, | ||
#[pin] | ||
_pin: PhantomPinned, | ||
} | ||
} | ||
|
||
/// Tries to write some bytes from the given `buf` to the writer in an | ||
/// asynchronous manner, returning a future. | ||
pub(crate) fn write_buf<'a, W, B>(writer: &'a mut W, buf: &'a mut B) -> WriteBuf<'a, W, B> | ||
where | ||
W: AsyncWrite + Unpin, | ||
B: Buf, | ||
{ | ||
WriteBuf { | ||
writer, | ||
buf, | ||
_pin: PhantomPinned, | ||
} | ||
} | ||
|
||
impl<W, B> Future for WriteBuf<'_, W, B> | ||
where | ||
W: AsyncWrite + Unpin, | ||
B: Buf, | ||
{ | ||
type Output = io::Result<usize>; | ||
|
||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<usize>> { | ||
let me = self.project(); | ||
|
||
if !me.buf.has_remaining() { | ||
return Poll::Ready(Ok(0)); | ||
} | ||
|
||
let n = ready!(Pin::new(me.writer).poll_write(cx, me.buf.bytes()))?; | ||
me.buf.advance(n); | ||
Poll::Ready(Ok(n)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.