diff --git a/examples/new_read.rs b/examples/new_read.rs index fac40e69c..651697843 100644 --- a/examples/new_read.rs +++ b/examples/new_read.rs @@ -1,19 +1,18 @@ +use rustix::buffer::extend; use rustix::io::read; use rustix::stdio::stdin; use std::mem::MaybeUninit; fn main() { - let buf = vec![0_u8; 3]; - let _x: Vec = read(stdin(), buf).unwrap(); - let mut buf = vec![0_u8; 3]; + let _x: () = read(stdin(), extend(&mut buf)).unwrap(); let _x: usize = read(stdin(), &mut buf).unwrap(); let _x: usize = read(stdin(), &mut *buf).unwrap(); + let _x: usize = read(stdin(), &mut buf[..]).unwrap(); + let _x: usize = read(stdin(), &mut (*buf)[..]).unwrap(); let mut buf = [0, 0, 0]; let _x: usize = read(stdin(), &mut buf).unwrap(); - - let mut buf = [0, 0, 0]; let _x: usize = read(stdin(), &mut buf[..]).unwrap(); let mut buf = [ @@ -22,12 +21,6 @@ fn main() { MaybeUninit::uninit(), ]; let _x: (&mut [u8], &mut [MaybeUninit]) = read(stdin(), &mut buf).unwrap(); - - let mut buf = [ - MaybeUninit::uninit(), - MaybeUninit::uninit(), - MaybeUninit::uninit(), - ]; let _x: (&mut [u8], &mut [MaybeUninit]) = read(stdin(), &mut buf[..]).unwrap(); // This is reduced from src/fs/inotify.rs line 177. diff --git a/src/buffer.rs b/src/buffer.rs index cea429e68..6167bf6ef 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -13,10 +13,12 @@ pub trait Buffer: private::Sealed {} // Implement `Buffer` for all the types that implement `Sealed`. impl Buffer for &mut [T] {} impl Buffer for &mut [T; N] {} +#[cfg(feature = "alloc")] impl Buffer for &mut Vec {} impl<'a, T> Buffer for &'a mut [MaybeUninit] {} impl<'a, T, const N: usize> Buffer for &'a mut [MaybeUninit; N] {} -impl Buffer for Vec {} +#[cfg(feature = "alloc")] +impl<'a, T> Buffer for Extend<'a, T> {} impl private::Sealed for &mut [T] { type Result = usize; @@ -49,6 +51,7 @@ impl private::Sealed for &mut [T; N] { // `Vec` implements `DerefMut` to `&mut [T]`, however it doesn't get // auto-derefed in a `impl Buffer`, so we add this `impl` so that our users // don't have to add an extra `*` in these situations. +#[cfg(feature = "alloc")] impl private::Sealed for &mut Vec { type Result = usize; @@ -101,20 +104,34 @@ impl<'a, T, const N: usize> private::Sealed for &'a mut [MaybeUninit; N] { } } +/// A type that implements [`Buffer`] by appending to a `Vec`, up to its +/// capacity. +/// +/// Because this uses the capacity, and never reallocates, it's a good idea to +/// reserve some space in a `Vec` before using this! +#[cfg(feature = "alloc")] +pub struct Extend<'a, T>(&'a mut Vec); + +/// Construct an [`Extend`]. +#[cfg(feature = "alloc")] +pub fn extend(v: &mut Vec) -> Extend { + Extend(v) +} + #[cfg(feature = "alloc")] -impl private::Sealed for Vec { - type Result = Vec; +impl<'a, T> private::Sealed for Extend<'a, T> { + /// The mutated `Vec` reflects the number of bytes read. + type Result = (); #[inline] fn as_raw_parts_mut(&mut self) -> (*mut T, usize) { - self.clear(); - (self.as_mut_ptr(), self.capacity()) + let spare = self.0.spare_capacity_mut(); + (spare.as_mut_ptr().cast(), spare.len()) } #[inline] - unsafe fn finish(mut self, len: usize) -> Self::Result { - self.set_len(len); - self + unsafe fn finish(self, len: usize) -> Self::Result { + self.0.set_len(self.0.len() + len); } } diff --git a/src/lib.rs b/src/lib.rs index 85da4c858..d5a82a110 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -156,8 +156,7 @@ extern crate static_assertions; #[allow(unused_imports)] mod static_assertions; -// Internal utilities. -mod buffer; +pub mod buffer; #[cfg(not(windows))] #[macro_use] pub(crate) mod cstr;