@@ -1000,6 +1000,94 @@ pub unsafe trait FromBytes: FromZeroes {
1000
1000
where
1001
1001
Self : Sized ;
1002
1002
1003
+ /// Interprets the given `bytes` as a `&Self` without copying.
1004
+ ///
1005
+ /// If `bytes.len() != size_of::<T>()` or `bytes` is not aligned to
1006
+ /// `align_of::<T>()`, this returns `None`.
1007
+ #[ inline]
1008
+ fn ref_from ( bytes : & [ u8 ] ) -> Option < & Self >
1009
+ where
1010
+ Self : Sized ,
1011
+ {
1012
+ Ref :: < & [ u8 ] , Self > :: new ( bytes) . map ( Ref :: into_ref)
1013
+ }
1014
+
1015
+ /// Interprets the prefix of the given `bytes` as a `&Self` without copying.
1016
+ ///
1017
+ /// `ref_from_prefix` returns a reference to the first `size_of::<Self>()`
1018
+ /// bytes of `bytes`. If `bytes.len() != size_of::<T>()` or `bytes` is not
1019
+ /// aligned to `align_of::<T>()`, this returns `None`.
1020
+ ///
1021
+ /// To also access the prefix bytes, use [`Ref::new_from_prefix`]. Then,
1022
+ /// use [`Ref::into_ref`] to get a `&Self` with the same lifetime.
1023
+ #[ inline]
1024
+ fn ref_from_prefix ( bytes : & [ u8 ] ) -> Option < & Self >
1025
+ where
1026
+ Self : Sized ,
1027
+ {
1028
+ Ref :: < & [ u8 ] , Self > :: new_from_prefix ( bytes) . map ( |( r, _) | r. into_ref ( ) )
1029
+ }
1030
+
1031
+ /// Interprets the suffix of the given `bytes` as a `&Self` without copying.
1032
+ ///
1033
+ /// `ref_from_suffix` returns a reference to the last `size_of::<Self>()`
1034
+ /// bytes of `bytes`. If `bytes.len() != size_of::<T>()` or the suffix of
1035
+ /// `bytes` is not aligned to `align_of::<T>()`, this returns `None`.
1036
+ ///
1037
+ /// To also access the suffix bytes, use [`Ref::new_from_suffix`]. Then,
1038
+ /// use [`Ref::into_ref`] to get a `&Self` with the same lifetime.
1039
+ #[ inline]
1040
+ fn ref_from_suffix ( bytes : & [ u8 ] ) -> Option < & Self >
1041
+ where
1042
+ Self : Sized ,
1043
+ {
1044
+ Ref :: < & [ u8 ] , Self > :: new_from_suffix ( bytes) . map ( |( _, r) | r. into_ref ( ) )
1045
+ }
1046
+
1047
+ /// Interprets the given `bytes` as a `&mut Self` without copying.
1048
+ ///
1049
+ /// If `bytes.len() != size_of::<T>()` or `bytes` is not aligned to
1050
+ /// `align_of::<T>()`, this returns `None`.
1051
+ #[ inline]
1052
+ fn mut_from ( bytes : & mut [ u8 ] ) -> Option < & mut Self >
1053
+ where
1054
+ Self : Sized + AsBytes ,
1055
+ {
1056
+ Ref :: < & mut [ u8 ] , Self > :: new ( bytes) . map ( Ref :: into_mut)
1057
+ }
1058
+
1059
+ /// Interprets the prefix of the given `bytes` as a `&mut Self` without copying.
1060
+ ///
1061
+ /// `mut_from_prefix` returns a reference to the first `size_of::<Self>()`
1062
+ /// bytes of `bytes`. If `bytes.len() != size_of::<T>()` or `bytes` is not
1063
+ /// aligned to `align_of::<T>()`, this returns `None`.
1064
+ ///
1065
+ /// To also access the prefix bytes, use [`Ref::new_from_prefix`]. Then,
1066
+ /// use [`Ref::into_mut`] to get a `&mut Self` with the same lifetime.
1067
+ #[ inline]
1068
+ fn mut_from_prefix ( bytes : & mut [ u8 ] ) -> Option < & mut Self >
1069
+ where
1070
+ Self : Sized + AsBytes ,
1071
+ {
1072
+ Ref :: < & mut [ u8 ] , Self > :: new_from_prefix ( bytes) . map ( |( r, _) | r. into_mut ( ) )
1073
+ }
1074
+
1075
+ /// Interprets the suffix of the given `bytes` as a `&mut Self` without copying.
1076
+ ///
1077
+ /// `mut_from_suffix` returns a reference to the last `size_of::<Self>()`
1078
+ /// bytes of `bytes`. If `bytes.len() != size_of::<T>()` or the suffix of
1079
+ /// `bytes` is not aligned to `align_of::<T>()`, this returns `None`.
1080
+ ///
1081
+ /// To also access the suffix bytes, use [`Ref::new_from_suffix`]. Then,
1082
+ /// use [`Ref::into_mut`] to get a `&mut Self` with the same lifetime.
1083
+ #[ inline]
1084
+ fn mut_from_suffix ( bytes : & mut [ u8 ] ) -> Option < & mut Self >
1085
+ where
1086
+ Self : Sized + AsBytes ,
1087
+ {
1088
+ Ref :: < & mut [ u8 ] , Self > :: new_from_suffix ( bytes) . map ( |( _, r) | r. into_mut ( ) )
1089
+ }
1090
+
1003
1091
/// Reads a copy of `Self` from `bytes`.
1004
1092
///
1005
1093
/// If `bytes.len() != size_of::<Self>()`, `read_from` returns `None`.
@@ -1008,8 +1096,7 @@ pub unsafe trait FromBytes: FromZeroes {
1008
1096
where
1009
1097
Self : Sized ,
1010
1098
{
1011
- let r = Ref :: < _ , Unalign < Self > > :: new_unaligned ( bytes) ?;
1012
- Some ( r. read ( ) . into_inner ( ) )
1099
+ Ref :: < _ , Unalign < Self > > :: new_unaligned ( bytes) . map ( |r| r. read ( ) . into_inner ( ) )
1013
1100
}
1014
1101
1015
1102
/// Reads a copy of `Self` from the prefix of `bytes`.
@@ -1022,8 +1109,8 @@ pub unsafe trait FromBytes: FromZeroes {
1022
1109
where
1023
1110
Self : Sized ,
1024
1111
{
1025
- let ( r , _suffix ) = Ref :: < _ , Unalign < Self > > :: new_unaligned_from_prefix ( bytes) ? ;
1026
- Some ( r. read ( ) . into_inner ( ) )
1112
+ Ref :: < _ , Unalign < Self > > :: new_unaligned_from_prefix ( bytes)
1113
+ . map ( | ( r , _ ) | r. read ( ) . into_inner ( ) )
1027
1114
}
1028
1115
1029
1116
/// Reads a copy of `Self` from the suffix of `bytes`.
@@ -1036,8 +1123,8 @@ pub unsafe trait FromBytes: FromZeroes {
1036
1123
where
1037
1124
Self : Sized ,
1038
1125
{
1039
- let ( _prefix , r ) = Ref :: < _ , Unalign < Self > > :: new_unaligned_from_suffix ( bytes) ? ;
1040
- Some ( r. read ( ) . into_inner ( ) )
1126
+ Ref :: < _ , Unalign < Self > > :: new_unaligned_from_suffix ( bytes)
1127
+ . map ( | ( _ , r ) | r. read ( ) . into_inner ( ) )
1041
1128
}
1042
1129
}
1043
1130
@@ -4425,6 +4512,69 @@ mod tests {
4425
4512
}
4426
4513
}
4427
4514
4515
+ #[ test]
4516
+ fn test_ref_from_mut_from ( ) {
4517
+ // Test `FromBytes::{ref_from, mut_from}{,_prefix,_suffix}` success cases
4518
+ // Exhaustive coverage for these methods is covered by the `Ref` tests above,
4519
+ // which these helper methods defer to.
4520
+
4521
+ let mut buf =
4522
+ Align :: < [ u8 ; 16 ] , AU64 > :: new ( [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 ] ) ;
4523
+
4524
+ assert_eq ! (
4525
+ AU64 :: ref_from( & buf. t[ 8 ..] ) . unwrap( ) . 0 . to_ne_bytes( ) ,
4526
+ [ 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 ]
4527
+ ) ;
4528
+ let suffix = AU64 :: mut_from ( & mut buf. t [ 8 ..] ) . unwrap ( ) ;
4529
+ suffix. 0 = 0x0101010101010101 ;
4530
+ assert_eq ! ( <[ u8 ; 9 ] >:: ref_from_suffix( & buf. t[ ..] ) . unwrap( ) , & [ 7u8 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ] ) ;
4531
+ let suffix = AU64 :: mut_from_suffix ( & mut buf. t [ 1 ..] ) . unwrap ( ) ;
4532
+ suffix. 0 = 0x0202020202020202 ;
4533
+ <[ u8 ; 10 ] >:: mut_from_suffix ( & mut buf. t [ ..] ) . unwrap ( ) [ 0 ] = 42 ;
4534
+ assert_eq ! ( <[ u8 ; 9 ] >:: ref_from_prefix( & buf. t[ ..] ) . unwrap( ) , & [ 0 , 1 , 2 , 3 , 4 , 5 , 42 , 7 , 2 ] ) ;
4535
+ <[ u8 ; 2 ] >:: mut_from_prefix ( & mut buf. t [ ..] ) . unwrap ( ) [ 1 ] = 30 ;
4536
+ assert_eq ! ( buf. t, [ 0 , 30 , 2 , 3 , 4 , 5 , 42 , 7 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 ] ) ;
4537
+ }
4538
+
4539
+ #[ test]
4540
+ fn test_ref_from_mut_from_error ( ) {
4541
+ // Test `FromBytes::{ref_from, mut_from}{,_prefix,_suffix}` error cases.
4542
+
4543
+ // Fail because the buffer is too large.
4544
+ let mut buf = Align :: < [ u8 ; 16 ] , AU64 > :: default ( ) ;
4545
+ // `buf.t` should be aligned to 8, so only the length check should fail.
4546
+ assert ! ( AU64 :: ref_from( & buf. t[ ..] ) . is_none( ) ) ;
4547
+ assert ! ( AU64 :: mut_from( & mut buf. t[ ..] ) . is_none( ) ) ;
4548
+ assert ! ( <[ u8 ; 8 ] >:: ref_from( & buf. t[ ..] ) . is_none( ) ) ;
4549
+ assert ! ( <[ u8 ; 8 ] >:: mut_from( & mut buf. t[ ..] ) . is_none( ) ) ;
4550
+
4551
+ // Fail because the buffer is too small.
4552
+ let mut buf = Align :: < [ u8 ; 4 ] , AU64 > :: default ( ) ;
4553
+ assert ! ( AU64 :: ref_from( & buf. t[ ..] ) . is_none( ) ) ;
4554
+ assert ! ( AU64 :: mut_from( & mut buf. t[ ..] ) . is_none( ) ) ;
4555
+ assert ! ( <[ u8 ; 8 ] >:: ref_from( & buf. t[ ..] ) . is_none( ) ) ;
4556
+ assert ! ( <[ u8 ; 8 ] >:: mut_from( & mut buf. t[ ..] ) . is_none( ) ) ;
4557
+ assert ! ( AU64 :: ref_from_prefix( & buf. t[ ..] ) . is_none( ) ) ;
4558
+ assert ! ( AU64 :: mut_from_prefix( & mut buf. t[ ..] ) . is_none( ) ) ;
4559
+ assert ! ( AU64 :: ref_from_suffix( & buf. t[ ..] ) . is_none( ) ) ;
4560
+ assert ! ( AU64 :: mut_from_suffix( & mut buf. t[ ..] ) . is_none( ) ) ;
4561
+ assert ! ( <[ u8 ; 8 ] >:: ref_from_prefix( & buf. t[ ..] ) . is_none( ) ) ;
4562
+ assert ! ( <[ u8 ; 8 ] >:: mut_from_prefix( & mut buf. t[ ..] ) . is_none( ) ) ;
4563
+ assert ! ( <[ u8 ; 8 ] >:: ref_from_suffix( & buf. t[ ..] ) . is_none( ) ) ;
4564
+ assert ! ( <[ u8 ; 8 ] >:: mut_from_suffix( & mut buf. t[ ..] ) . is_none( ) ) ;
4565
+
4566
+ // Fail because the alignment is insufficient.
4567
+ let mut buf = Align :: < [ u8 ; 13 ] , AU64 > :: default ( ) ;
4568
+ assert ! ( AU64 :: ref_from( & buf. t[ 1 ..] ) . is_none( ) ) ;
4569
+ assert ! ( AU64 :: mut_from( & mut buf. t[ 1 ..] ) . is_none( ) ) ;
4570
+ assert ! ( AU64 :: ref_from( & buf. t[ 1 ..] ) . is_none( ) ) ;
4571
+ assert ! ( AU64 :: mut_from( & mut buf. t[ 1 ..] ) . is_none( ) ) ;
4572
+ assert ! ( AU64 :: ref_from_prefix( & buf. t[ 1 ..] ) . is_none( ) ) ;
4573
+ assert ! ( AU64 :: mut_from_prefix( & mut buf. t[ 1 ..] ) . is_none( ) ) ;
4574
+ assert ! ( AU64 :: ref_from_suffix( & buf. t[ ..] ) . is_none( ) ) ;
4575
+ assert ! ( AU64 :: mut_from_suffix( & mut buf. t[ ..] ) . is_none( ) ) ;
4576
+ }
4577
+
4428
4578
#[ test]
4429
4579
#[ allow( clippy:: cognitive_complexity) ]
4430
4580
fn test_new_error ( ) {
0 commit comments