//! Read into uninitialized bytes logic. use_prelude!(); use ::std::io::Read; /// Trait for a [`Read`](https://doc.rust-lang.org/std/io/trait.Read.html)able /// type that can output the bytes read into /// [uninitialised memory][`MaybeUninit`]. /// /// # Safety (to implement) / Guarantees (for users of `impl ReadIntoUninit` types) /// /// The trait is `unsafe` (to implement) because it **needs to guarantee** to /// users of generic `R : ReadIntoUninit` code (that may use `unsafe` code /// relying on it!) that: /// /// - `if let Ok(init_buf) = self.read_into_uninit(buf)`, then it must be /// sound to: /// /// ```rust /// # macro_rules! ignore {($($t:tt)*) => ()} ignore! { /// unsafe { /// buf.get_out_unchecked(.. init_buf.len()).assume_init() /// } /// # } /// ``` /// /// - `if self.read_into_uninit_exact(buf).is_ok()`, then it must be /// sound to: `buf.assume_init()`. /// /// # Counterexample /// /// ```rust,no_run /// #![feature(specialization)] /// use ::uninit::{prelude::*, /// read::{auto_impl, ReadIntoUninit}, /// }; /// /// pub /// struct Evil; /// /// auto_impl! { #[derived_from(ReadIntoUninit)] impl Read for Evil } /// unsafe // unsound! /// impl ReadIntoUninit for Evil { /// fn read_into_uninit<'buf> ( /// self: &'_ mut Self, /// buf: Out<'buf, [u8]>, /// ) -> ::std::io::Result<&'buf mut [u8]> /// { /// Ok(Box::leak(vec![0; buf.len()].into_boxed_slice())) /// } /// } /// ``` /// /// Indeed, with such an impl, the following function could cause UB, when /// instanced with `R = Evil`: /// /// ```rust /// use ::uninit::{prelude::*, read::ReadIntoUninit}; /// /// fn read_byte (reader: &'_ mut R) /// -> ::std::io::Result /// where /// R : ReadIntoUninit, /// { /// let mut byte = MaybeUninit::uninit(); /// reader.read_into_uninit_exact(::std::slice::from_mut(&mut byte).as_out())?; /// Ok(unsafe { /// // Safety: Guaranteed by `ReadIntoUninit` contract /// byte.assume_init() /// }) /// } /// ``` pub unsafe trait ReadIntoUninit: Read // Safety: `.read_into_uninit_exact()` delegates to `.read_into_uninit()`. { /// Single attempt to read bytes from `Self` into `buf`. /// /// On success, it returns the bytes having been read. /// /// # Guarantees (that `unsafe` code may rely on) /// /// - `if let Ok(init_buf) = self.read_into_uninit(buf)`, then it is /// sound to: /// /// ```rust /// # macro_rules! ignore {($($t:tt)*) => ()} ignore! { /// unsafe { /// buf.get_out_unchecked(.. init_buf.len()).assume_init() /// } /// # } /// ``` /// /// This is not guaranteed to read `buf.len()` bytes, see the docs of /// [`.read()`][`Read::read`] for more information. fn read_into_uninit<'buf>( self: &'_ mut Self, buf: Out<'buf, [u8]>, ) -> io::Result<&'buf mut [u8]>; /// Attempts to _fill_ `buf` through multiple `.read()` calls if necessary. /// /// On success, it returns the bytes having been read. /// /// # Guarantees (that `unsafe` code may rely on) /// /// - `if self.read_into_uninit_exact(buf).is_ok()`, then it is /// sound to: `buf.assume_init()`. /// /// See the docs of [`.read_exact()`][`Read::read_exact`] for more /// information. fn read_into_uninit_exact<'buf>( self: &'_ mut Self, mut buf: Out<'buf, [u8]>, ) -> io::Result<&'buf mut [u8]> { { let mut buf = buf.reborrow(); while buf.is_empty().not() { match self.read_into_uninit(buf.r()).map(|it| it.len()) { Ok(0) => { return Err(io::Error::new( io::ErrorKind::UnexpectedEof, "failed to fill whole buffer", )); } Ok(n) => { // buf = &mut buf[n ..]; buf = buf.get_out(n..).unwrap(); } Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {} Err(e) => { return Err(e); } } } } Ok(unsafe { // # Safety // // - this is the "concatenation" of all the "buf[.. n]" // initialisation witnesses. buf.assume_init() }) } /// Chains / concats two `ReadIntoUninit` readers into one. #[cfg(feature = "chain")] #[cfg_attr(feature = "nightly", doc(cfg(feature = "chain")))] fn chain(self: Self, next: R) -> chain::Chain where Self: Sized, { chain::Chain { first: self, second: next, first_done: false, } } } /// Helper macro to alleviate the code duplication from implementing both /// `Read` and `ReadIntoUninit`. /// /// Once some type `T` implements `ReadIntoUninit`, you can derive `Read` by /// doing: /// /// ```rust /// # macro_rules! ignore {($($t:tt)*) => ()} ignore! { /// ::uninit::read::auto_impl! { /// #[derived_from(ReadIntoUninit)] /// impl Read for X /// } /// // and if X is generic, over, for instance, `Generics` /// ::uninit::read::auto_impl! { /// #[derived_from(ReadIntoUninit)] /// impl[Generics] Read for X /// } /// # } /// ``` #[doc(hidden)] #[macro_export] macro_rules! _private_auto_impl {( #[derived_from(ReadIntoUninit)] impl $( [$($generics:tt)*] )? Read for $T:ty $( where $($where_clause:tt)* )? ) => ( impl$(<$($generics)*>)? $crate::std::io::Read for $T where $( $($where_clause)* )? { #[inline] fn read (self: &'_ mut Self, buf: &'_ mut [u8]) -> $crate::std::io::Result { ::read_into_uninit( self, buf.as_out(), ).map(|x| x.len()) } #[inline] fn read_exact (self: &'_ mut Self, buf: &'_ mut [u8]) -> $crate::std::io::Result<()> { ::read_into_uninit_exact( self, buf.as_out(), ).map(drop) } } )} #[doc(inline)] pub use _private_auto_impl as auto_impl; pub use crate::extension_traits::VecExtendFromReader; mod impls; #[cfg(feature = "chain")] #[cfg_attr(feature = "nightly", doc(cfg(feature = "chain")))] pub mod chain { #![allow(missing_docs)] use super::*; #[cfg_attr(feature = "nightly", doc(cfg(feature = "chain")))] #[derive(Debug)] pub struct Chain where R1: ReadIntoUninit, R2: ReadIntoUninit, { pub(super) first: R1, pub(super) second: R2, pub(super) first_done: bool, } impl Chain where R1: ReadIntoUninit, R2: ReadIntoUninit, { pub fn into_inner(self: Self) -> (R1, R2) { let Self { first, second, .. } = self; (first, second) } pub fn get_ref(self: &'_ Self) -> (&'_ R1, &'_ R2) { let Self { first, second, .. } = self; (first, second) } } unsafe impl ReadIntoUninit for Chain where R1: ReadIntoUninit, R2: ReadIntoUninit, { fn read_into_uninit<'buf>( self: &'_ mut Self, mut buf: Out<'buf, [u8]>, ) -> io::Result<&'buf mut [u8]> { let len = buf.len(); if len == 0 { return Ok(buf.copy_from_slice(&[])); } if self.first_done.not() { let buf_ = self.first.read_into_uninit(buf.r())?; if buf_.is_empty() { self.first_done = true; } else { return unsafe { // Safety: `buf_` has been a witness of the // initialization of these bytes. let len = buf_.len(); let buf = buf.get_out(..len).unwrap(); Ok(buf.assume_init()) }; } } self.second.read_into_uninit(buf) } } super::auto_impl! { #[derived_from(ReadIntoUninit)] impl[R1, R2] Read for Chain where R1 : ReadIntoUninit, R2 : ReadIntoUninit, } }