@@ -2696,7 +2696,7 @@ pub unsafe trait TryFromBytes {
26962696 } ;
26972697 // SAFETY: `candidate` was copied from from `source: &[u8]`, so all of
26982698 // its bytes are initialized.
2699- unsafe { try_read_from ( source, candidate) }
2699+ unsafe { try_read_from ( source, candidate) } . map_err ( TryReadError :: Validity )
27002700 }
27012701
27022702 /// Attempts to read a `Self` from the prefix of the given `source`.
@@ -2757,7 +2757,10 @@ pub unsafe trait TryFromBytes {
27572757 } ;
27582758 // SAFETY: `candidate` was copied from from `source: &[u8]`, so all of
27592759 // its bytes are initialized.
2760- unsafe { try_read_from ( source, candidate) . map ( |slf| ( slf, suffix) ) }
2760+ match unsafe { try_read_from ( source, candidate) } {
2761+ Ok ( slf) => Ok ( ( slf, suffix) ) ,
2762+ Err ( err) => Err ( TryReadError :: Validity ( err) ) ,
2763+ }
27612764 }
27622765
27632766 /// Attempts to read a `Self` from the suffix of the given `source`.
@@ -2819,7 +2822,77 @@ pub unsafe trait TryFromBytes {
28192822 } ;
28202823 // SAFETY: `candidate` was copied from from `source: &[u8]`, so all of
28212824 // its bytes are initialized.
2822- unsafe { try_read_from ( source, candidate) . map ( |slf| ( prefix, slf) ) }
2825+ match unsafe { try_read_from ( source, candidate) } {
2826+ Ok ( slf) => Ok ( ( prefix, slf) ) ,
2827+ Err ( err) => Err ( TryReadError :: Validity ( err) ) ,
2828+ }
2829+ }
2830+
2831+ /// Attempts to read a copy of `self` from an `io::Read`.
2832+ ///
2833+ /// This is useful for interfacing with operating system byte sinks (files,
2834+ /// sockets, etc.).
2835+ ///
2836+ /// # Examples
2837+ ///
2838+ /// ```no_run
2839+ /// use zerocopy::{byteorder::big_endian::*, TryFromBytes, Unalign};
2840+ /// use std::fs::File;
2841+ /// # use zerocopy_derive::*;
2842+ ///
2843+ /// #[derive(TryFromBytes)]
2844+ /// #[repr(C)]
2845+ /// struct BitmapFileHeader {
2846+ /// signature: Unalign<Signature>,
2847+ /// size: U32,
2848+ /// reserved: U64,
2849+ /// offset: U64,
2850+ /// }
2851+ ///
2852+ /// #[derive(TryFromBytes)]
2853+ /// #[repr(u16)]
2854+ /// enum Signature {
2855+ /// BM = u16::from_ne_bytes(*b"BM")
2856+ /// }
2857+ ///
2858+ /// let mut file = File::open("image.bin").unwrap();
2859+ /// let header = BitmapFileHeader::try_read_from_io(&mut file)
2860+ /// .expect("read failed")
2861+ /// .expect("invalid header");
2862+ /// ```
2863+ // TODO: Write tests for this method
2864+ #[ cfg( feature = "std" ) ]
2865+ #[ inline( always) ]
2866+ fn try_read_from_io < R > ( mut src : R ) -> io:: Result < Result < Self , ValidityError < & ' static ( ) , Self > > >
2867+ where
2868+ Self : Sized ,
2869+ R : io:: Read ,
2870+ {
2871+ // NOTE(#2319, #2320): We do `buf.zero()` separately rather than
2872+ // constructing `let buf = CoreMaybeUninit::zeroed()` because, if `Self`
2873+ // contains padding bytes, then a typed copy of `CoreMaybeUninit<Self>`
2874+ // will not necessarily preserve zeros written to those padding byte
2875+ // locations, and so `buf` could contain uninitialized bytes.
2876+ let mut buf = CoreMaybeUninit :: < Self > :: uninit ( ) ;
2877+ buf. zero ( ) ;
2878+
2879+ let ptr = Ptr :: from_mut ( & mut buf) ;
2880+ // SAFETY: After `buf.zero()`, `buf` consists entirely of initialized,
2881+ // zeroed bytes. Since `MaybeUninit` has no validity requirements, `ptr`
2882+ // cannot be used to write values which will violate `buf`'s bit
2883+ // validity. Since `ptr` has `Exclusive` aliasing, nothing other than
2884+ // `ptr` may be used to mutate `ptr`'s referent, and so its bit validity
2885+ // cannot be violated even though `buf` may have more permissive bit
2886+ // validity than `ptr`.
2887+ let ptr = unsafe { ptr. assume_validity :: < invariant:: Initialized > ( ) } ;
2888+ let ptr = ptr. as_bytes :: < BecauseExclusive > ( ) ;
2889+ src. read_exact ( ptr. as_mut ( ) ) ?;
2890+
2891+ // SAFETY: `buf` entirely consists of initialized bytes.
2892+ Ok ( match unsafe { try_read_from ( ( ) , buf) } {
2893+ Ok ( slf) => Ok ( slf) ,
2894+ Err ( err) => Err ( err. map_src ( |_| [ ] ) ) ,
2895+ } )
28232896 }
28242897}
28252898
@@ -2885,7 +2958,7 @@ fn swap<T, U>((t, u): (T, U)) -> (U, T) {
28852958unsafe fn try_read_from < S , T : TryFromBytes > (
28862959 source : S ,
28872960 mut candidate : CoreMaybeUninit < T > ,
2888- ) -> Result < T , TryReadError < S , T > > {
2961+ ) -> Result < T , ValidityError < S , T > > {
28892962 // We use `from_mut` despite not mutating via `c_ptr` so that we don't need
28902963 // to add a `T: Immutable` bound.
28912964 let c_ptr = Ptr :: from_mut ( & mut candidate) ;
@@ -2911,7 +2984,7 @@ unsafe fn try_read_from<S, T: TryFromBytes>(
29112984 // `Self: !Immutable`. Since `Self: Immutable`, this panic condition will
29122985 // not happen.
29132986 if !Wrapping :: < T > :: is_bit_valid ( c_ptr. forget_aligned ( ) ) {
2914- return Err ( ValidityError :: new ( source) . into ( ) ) ;
2987+ return Err ( ValidityError :: new ( source) ) ;
29152988 }
29162989
29172990 fn _assert_same_size_and_validity < T > ( )
0 commit comments