@@ -616,6 +616,36 @@ where
616616 // SAFETY: We don't call any methods on `b` other than those provided by
617617 // `IntoByteSlice`.
618618 let b = unsafe { r. into_byte_slice ( ) } ;
619+ let b = b. into_byte_slice ( ) ;
620+
621+ if let crate :: layout:: SizeInfo :: Sized { .. } = T :: LAYOUT . size_info {
622+ let ptr = Ptr :: from_ref ( b) ;
623+ // SAFETY: `T::raw_from_ptr_len` promises to preserve address and provenance in the referent
624+ let ptr: Ptr < ' _ , T , _ > = unsafe {
625+ ptr. transmute_unchecked ( |ptr| {
626+ let ptr = T :: raw_from_ptr_len (
627+ ptr. as_non_null ( ) . cast ( ) ,
628+ <T :: PointerMetadata as crate :: PointerMetadata >:: from_elem_count ( 0 ) ,
629+ ) ;
630+ // SAFETY: The safety invariants of `Ptr::new` (see definition) are
631+ // satisfied:
632+ // 0. If `ptr`'s referent is not zero sized, then `ptr` has valid
633+ // provenance for its referent, because it derived from `self`
634+ // using a series of provenance-preserving operations, and
635+ // because `self` has valid provenance for its referent. By the
636+ // same argument, `ptr`'s referent is entirely contained within
637+ // the same allocated object as `self`'s referent.
638+ // 1. If `ptr`'s referent is not zero sized, then the allocation of
639+ // `ptr` is guaranteed to live for at least `'a`, because `ptr`
640+ // is entirely contained in `self`, which lives for at least `'a`
641+ // by invariant on `Ptr`.
642+ unsafe { crate :: pointer:: PtrInner :: new ( ptr) }
643+ } )
644+ } ;
645+ // SAFETY: By invariant on `r`, we know that size and alignment are valid.
646+ let ptr = unsafe { ptr. assume_alignment ( ) } ;
647+ return ptr. as_ref ( ) ;
648+ }
619649
620650 // PANICS: By post-condition on `into_byte_slice`, `b`'s size and
621651 // alignment are valid for `T`. By post-condition, `b.into_byte_slice()`
@@ -650,6 +680,36 @@ where
650680 // SAFETY: We don't call any methods on `b` other than those provided by
651681 // `IntoByteSliceMut`.
652682 let b = unsafe { r. into_byte_slice_mut ( ) } ;
683+ let b = b. into_byte_slice_mut ( ) ;
684+
685+ if let crate :: layout:: SizeInfo :: Sized { .. } = T :: LAYOUT . size_info {
686+ let ptr = Ptr :: from_mut ( b) ;
687+ // SAFETY: `T::raw_from_ptr_len` promises to preserve address and provenance in the referent
688+ let ptr: Ptr < ' _ , T , _ > = unsafe {
689+ ptr. transmute_unchecked ( |ptr| {
690+ let ptr = T :: raw_from_ptr_len (
691+ ptr. as_non_null ( ) . cast ( ) ,
692+ <T :: PointerMetadata as crate :: PointerMetadata >:: from_elem_count ( 0 ) ,
693+ ) ;
694+ // SAFETY: The safety invariants of `Ptr::new` (see definition) are
695+ // satisfied:
696+ // 0. If `ptr`'s referent is not zero sized, then `ptr` has valid
697+ // provenance for its referent, because it derived from `self`
698+ // using a series of provenance-preserving operations, and
699+ // because `self` has valid provenance for its referent. By the
700+ // same argument, `ptr`'s referent is entirely contained within
701+ // the same allocated object as `self`'s referent.
702+ // 1. If `ptr`'s referent is not zero sized, then the allocation of
703+ // `ptr` is guaranteed to live for at least `'a`, because `ptr`
704+ // is entirely contained in `self`, which lives for at least `'a`
705+ // by invariant on `Ptr`.
706+ unsafe { crate :: pointer:: PtrInner :: new ( ptr) }
707+ } )
708+ } ;
709+ // SAFETY: By invariant on `r`, we know that size and alignment are valid.
710+ let ptr = unsafe { ptr. assume_alignment ( ) } ;
711+ return ptr. as_mut ( ) ;
712+ }
653713
654714 // PANICS: By post-condition on `into_byte_slice_mut`, `b`'s size and
655715 // alignment are valid for `T`. By post-condition,
@@ -763,11 +823,41 @@ where
763823 // SAFETY: We don't call any methods on `b` other than those provided by
764824 // `ByteSlice`.
765825 let b = unsafe { self . as_byte_slice ( ) } ;
826+ let b = b. deref ( ) ;
827+
828+ if let crate :: layout:: SizeInfo :: Sized { .. } = T :: LAYOUT . size_info {
829+ let ptr = Ptr :: from_ref ( b) ;
830+ // SAFETY: `T::raw_from_ptr_len` promises to preserve address and provenance in the referent
831+ let ptr: Ptr < ' _ , T , _ > = unsafe {
832+ ptr. transmute_unchecked ( |ptr| {
833+ let ptr = T :: raw_from_ptr_len (
834+ ptr. as_non_null ( ) . cast ( ) ,
835+ <T :: PointerMetadata as crate :: PointerMetadata >:: from_elem_count ( 0 ) ,
836+ ) ;
837+ // SAFETY: The safety invariants of `Ptr::new` (see definition) are
838+ // satisfied:
839+ // 0. If `ptr`'s referent is not zero sized, then `ptr` has valid
840+ // provenance for its referent, because it derived from `self`
841+ // using a series of provenance-preserving operations, and
842+ // because `self` has valid provenance for its referent. By the
843+ // same argument, `ptr`'s referent is entirely contained within
844+ // the same allocated object as `self`'s referent.
845+ // 1. If `ptr`'s referent is not zero sized, then the allocation of
846+ // `ptr` is guaranteed to live for at least `'a`, because `ptr`
847+ // is entirely contained in `self`, which lives for at least `'a`
848+ // by invariant on `Ptr`.
849+ unsafe { crate :: pointer:: PtrInner :: new ( ptr) }
850+ } )
851+ } ;
852+ // SAFETY: By invariant on `self`, we know that size and alignment are valid.
853+ let ptr = unsafe { ptr. assume_alignment ( ) } ;
854+ return ptr. as_ref ( ) ;
855+ }
766856
767857 // PANICS: By postcondition on `as_byte_slice`, `b`'s size and alignment
768858 // are valid for `T`, and by invariant on `ByteSlice`, these are
769859 // preserved through `.deref()`, so this `unwrap` will not panic.
770- let ptr = Ptr :: from_ref ( b. deref ( ) )
860+ let ptr = Ptr :: from_ref ( b)
771861 . try_cast_into_no_leftover :: < T , BecauseImmutable > ( None )
772862 . expect ( "zerocopy internal error: Deref::deref should be infallible" ) ;
773863 let ptr = ptr. recall_validity ( ) ;
@@ -791,12 +881,42 @@ where
791881 // SAFETY: We don't call any methods on `b` other than those provided by
792882 // `ByteSliceMut`.
793883 let b = unsafe { self . as_byte_slice_mut ( ) } ;
884+ let b = b. deref_mut ( ) ;
885+
886+ if let crate :: layout:: SizeInfo :: Sized { .. } = T :: LAYOUT . size_info {
887+ let ptr = Ptr :: from_mut ( b) ;
888+ // SAFETY: `T::raw_from_ptr_len` promises to preserve address and provenance in the referent
889+ let ptr: Ptr < ' _ , T , _ > = unsafe {
890+ ptr. transmute_unchecked ( |ptr| {
891+ let ptr = T :: raw_from_ptr_len (
892+ ptr. as_non_null ( ) . cast ( ) ,
893+ <T :: PointerMetadata as crate :: PointerMetadata >:: from_elem_count ( 0 ) ,
894+ ) ;
895+ // SAFETY: The safety invariants of `Ptr::new` (see definition) are
896+ // satisfied:
897+ // 0. If `ptr`'s referent is not zero sized, then `ptr` has valid
898+ // provenance for its referent, because it derived from `self`
899+ // using a series of provenance-preserving operations, and
900+ // because `self` has valid provenance for its referent. By the
901+ // same argument, `ptr`'s referent is entirely contained within
902+ // the same allocated object as `self`'s referent.
903+ // 1. If `ptr`'s referent is not zero sized, then the allocation of
904+ // `ptr` is guaranteed to live for at least `'a`, because `ptr`
905+ // is entirely contained in `self`, which lives for at least `'a`
906+ // by invariant on `Ptr`.
907+ unsafe { crate :: pointer:: PtrInner :: new ( ptr) }
908+ } )
909+ } ;
910+ // SAFETY: By invariant on `self`, we know that size and alignment are valid.
911+ let ptr = unsafe { ptr. assume_alignment ( ) } ;
912+ return ptr. as_mut ( ) ;
913+ }
794914
795915 // PANICS: By postcondition on `as_byte_slice_mut`, `b`'s size and
796916 // alignment are valid for `T`, and by invariant on `ByteSlice`, these
797917 // are preserved through `.deref_mut()`, so this `unwrap` will not
798918 // panic.
799- let ptr = Ptr :: from_mut ( b. deref_mut ( ) )
919+ let ptr = Ptr :: from_mut ( b)
800920 . try_cast_into_no_leftover :: < T , BecauseExclusive > ( None )
801921 . expect ( "zerocopy internal error: DerefMut::deref_mut should be infallible" ) ;
802922 let ptr = ptr. recall_validity :: < _ , ( _ , ( _ , ( BecauseExclusive , BecauseExclusive ) ) ) > ( ) ;
@@ -879,6 +999,48 @@ mod tests {
879999
8801000 use super :: * ;
8811001 use crate :: util:: testutil:: * ;
1002+ use test:: { self , Bencher } ;
1003+
1004+ #[ bench]
1005+ fn bench_from_bytes_sized ( b : & mut Bencher ) {
1006+ let buf = Align :: < [ u8 ; 8 ] , AU64 > :: default ( ) ;
1007+ // `buf.t` should be aligned to 8, so this should always succeed.
1008+ b. iter ( || test:: black_box ( Ref :: < _ , AU64 > :: from_bytes ( & buf. t [ ..] ) . unwrap ( ) ) ) ;
1009+ }
1010+
1011+ #[ bench]
1012+ fn bench_into_ref_sized ( b : & mut Bencher ) {
1013+ let buf = Align :: < [ u8 ; 8 ] , AU64 > :: default ( ) ;
1014+ b. iter ( || {
1015+ let r = Ref :: < _ , AU64 > :: from_bytes ( & buf. t [ ..] ) . unwrap ( ) ;
1016+ test:: black_box ( Ref :: into_ref ( r) )
1017+ } ) ;
1018+ }
1019+
1020+ #[ bench]
1021+ fn bench_into_mut_sized ( b : & mut Bencher ) {
1022+ let mut buf = Align :: < [ u8 ; 8 ] , AU64 > :: default ( ) ;
1023+ b. iter ( || {
1024+ let r = Ref :: < _ , AU64 > :: from_bytes ( & mut buf. t [ ..] ) . unwrap ( ) ;
1025+ test:: black_box ( Ref :: into_mut ( r) ) ;
1026+ } ) ;
1027+ }
1028+
1029+ #[ bench]
1030+ fn bench_deref_sized ( b : & mut Bencher ) {
1031+ let buf = Align :: < [ u8 ; 8 ] , AU64 > :: default ( ) ;
1032+ let r = Ref :: < _ , AU64 > :: from_bytes ( & buf. t [ ..] ) . unwrap ( ) ;
1033+ b. iter ( || test:: black_box ( r. deref ( ) ) ) ;
1034+ }
1035+
1036+ #[ bench]
1037+ fn bench_deref_mut_sized ( b : & mut Bencher ) {
1038+ let mut buf = Align :: < [ u8 ; 8 ] , AU64 > :: default ( ) ;
1039+ b. iter ( || {
1040+ let mut r = Ref :: < _ , AU64 > :: from_bytes ( & mut buf. t [ ..] ) . unwrap ( ) ;
1041+ test:: black_box ( r. deref_mut ( ) ) ;
1042+ } ) ;
1043+ }
8821044
8831045 #[ test]
8841046 fn test_mut_slice_into_ref ( ) {
0 commit comments