io: use a sealed trait to constrain VecWithInitialized (#3450)

This commit is contained in:
vitalyd 2021-01-21 05:32:42 -05:00 committed by GitHub
parent 117fc2ef3e
commit 5b7c7d565a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 20 additions and 10 deletions

View File

@ -1,4 +1,4 @@
use crate::io::util::vec_with_initialized::{into_read_buf_parts, VecWithInitialized};
use crate::io::util::vec_with_initialized::{into_read_buf_parts, VecU8, VecWithInitialized};
use crate::io::AsyncRead;
use pin_project_lite::pin_project;
@ -28,16 +28,15 @@ pub(crate) fn read_to_end<'a, R>(reader: &'a mut R, buffer: &'a mut Vec<u8>) ->
where
R: AsyncRead + Unpin + ?Sized,
{
// SAFETY: The generic type on VecWithInitialized is &mut Vec<u8>.
ReadToEnd {
reader,
buf: unsafe { VecWithInitialized::new(buffer) },
buf: VecWithInitialized::new(buffer),
read: 0,
_pin: PhantomPinned,
}
}
pub(super) fn read_to_end_internal<V: AsMut<Vec<u8>>, R: AsyncRead + ?Sized>(
pub(super) fn read_to_end_internal<V: VecU8, R: AsyncRead + ?Sized>(
buf: &mut VecWithInitialized<V>,
mut reader: Pin<&mut R>,
num_read: &mut usize,
@ -58,7 +57,7 @@ pub(super) fn read_to_end_internal<V: AsMut<Vec<u8>>, R: AsyncRead + ?Sized>(
/// Tries to read from the provided AsyncRead.
///
/// The length of the buffer is increased by the number of bytes read.
fn poll_read_to_end<V: AsMut<Vec<u8>>, R: AsyncRead + ?Sized>(
fn poll_read_to_end<V: VecU8, R: AsyncRead + ?Sized>(
buf: &mut VecWithInitialized<V>,
read: Pin<&mut R>,
cx: &mut Context<'_>,

View File

@ -38,10 +38,9 @@ where
R: AsyncRead + ?Sized + Unpin,
{
let buf = mem::replace(string, String::new()).into_bytes();
// SAFETY: The generic type of the VecWithInitialized is Vec<u8>.
ReadToString {
reader,
buf: unsafe { VecWithInitialized::new(buf) },
buf: VecWithInitialized::new(buf),
output: string,
read: 0,
_pin: PhantomPinned,

View File

@ -1,6 +1,19 @@
use crate::io::ReadBuf;
use std::mem::MaybeUninit;
mod private {
pub trait Sealed {}
impl Sealed for Vec<u8> {}
impl Sealed for &mut Vec<u8> {}
}
/// A sealed trait that constrains the generic type parameter in `VecWithInitialized<V>`. That struct's safety relies
/// on certain invariants upheld by `Vec<u8>`.
pub(crate) trait VecU8: AsMut<Vec<u8>> + private::Sealed {}
impl VecU8 for Vec<u8> {}
impl VecU8 for &mut Vec<u8> {}
/// This struct wraps a `Vec<u8>` or `&mut Vec<u8>`, combining it with a
/// `num_initialized`, which keeps track of the number of initialized bytes
/// in the unused capacity.
@ -28,10 +41,9 @@ impl VecWithInitialized<Vec<u8>> {
impl<V> VecWithInitialized<V>
where
V: AsMut<Vec<u8>>,
V: VecU8,
{
/// Safety: The generic parameter `V` must be either `Vec<u8>` or `&mut Vec<u8>`.
pub(crate) unsafe fn new(mut vec: V) -> Self {
pub(crate) fn new(mut vec: V) -> Self {
// SAFETY: The safety invariants of vector guarantee that the bytes up
// to its length are initialized.
Self {