@@ -1009,6 +1009,94 @@ pub unsafe trait FromBytes: FromZeroes {
1009
1009
where
1010
1010
Self : Sized ;
1011
1011
1012
+ /// Interprets the given `bytes` as a `&Self` without copying.
1013
+ ///
1014
+ /// If `bytes.len() != size_of::<T>()` or `bytes` is not aligned to
1015
+ /// `align_of::<T>()`, this returns `None`.
1016
+ #[ inline]
1017
+ fn ref_from ( bytes : & [ u8 ] ) -> Option < & Self >
1018
+ where
1019
+ Self : Sized ,
1020
+ {
1021
+ Ref :: < & [ u8 ] , Self > :: new ( bytes) . map ( Ref :: into_ref)
1022
+ }
1023
+
1024
+ /// Interprets the prefix of the given `bytes` as a `&Self` without copying.
1025
+ ///
1026
+ /// `ref_from_prefix` returns a reference to the first `size_of::<Self>()`
1027
+ /// bytes of `bytes`. If `bytes.len() != size_of::<T>()` or `bytes` is not
1028
+ /// aligned to `align_of::<T>()`, this returns `None`.
1029
+ ///
1030
+ /// To also access the prefix bytes, use [`Ref::new_from_prefix`]. Then,
1031
+ /// use [`Ref::into_ref`] to get a `&Self` with the same lifetime.
1032
+ #[ inline]
1033
+ fn ref_from_prefix ( bytes : & [ u8 ] ) -> Option < & Self >
1034
+ where
1035
+ Self : Sized ,
1036
+ {
1037
+ Ref :: < & [ u8 ] , Self > :: new_from_prefix ( bytes) . map ( |( r, _) | r. into_ref ( ) )
1038
+ }
1039
+
1040
+ /// Interprets the suffix of the given `bytes` as a `&Self` without copying.
1041
+ ///
1042
+ /// `ref_from_suffix` returns a reference to the last `size_of::<Self>()`
1043
+ /// bytes of `bytes`. If `bytes.len() != size_of::<T>()` or the suffix of
1044
+ /// `bytes` is not aligned to `align_of::<T>()`, this returns `None`.
1045
+ ///
1046
+ /// To also access the suffix bytes, use [`Ref::new_from_suffix`]. Then,
1047
+ /// use [`Ref::into_ref`] to get a `&Self` with the same lifetime.
1048
+ #[ inline]
1049
+ fn ref_from_suffix ( bytes : & [ u8 ] ) -> Option < & Self >
1050
+ where
1051
+ Self : Sized ,
1052
+ {
1053
+ Ref :: < & [ u8 ] , Self > :: new_from_suffix ( bytes) . map ( |( _, r) | r. into_ref ( ) )
1054
+ }
1055
+
1056
+ /// Interprets the given `bytes` as a `&mut Self` without copying.
1057
+ ///
1058
+ /// If `bytes.len() != size_of::<T>()` or `bytes` is not aligned to
1059
+ /// `align_of::<T>()`, this returns `None`.
1060
+ #[ inline]
1061
+ fn mut_from ( bytes : & mut [ u8 ] ) -> Option < & mut Self >
1062
+ where
1063
+ Self : Sized + AsBytes ,
1064
+ {
1065
+ Ref :: < & mut [ u8 ] , Self > :: new ( bytes) . map ( Ref :: into_mut)
1066
+ }
1067
+
1068
+ /// Interprets the prefix of the given `bytes` as a `&mut Self` without copying.
1069
+ ///
1070
+ /// `mut_from_prefix` returns a reference to the first `size_of::<Self>()`
1071
+ /// bytes of `bytes`. If `bytes.len() != size_of::<T>()` or `bytes` is not
1072
+ /// aligned to `align_of::<T>()`, this returns `None`.
1073
+ ///
1074
+ /// To also access the prefix bytes, use [`Ref::new_from_prefix`]. Then,
1075
+ /// use [`Ref::into_mut`] to get a `&mut Self` with the same lifetime.
1076
+ #[ inline]
1077
+ fn mut_from_prefix ( bytes : & mut [ u8 ] ) -> Option < & mut Self >
1078
+ where
1079
+ Self : Sized + AsBytes ,
1080
+ {
1081
+ Ref :: < & mut [ u8 ] , Self > :: new_from_prefix ( bytes) . map ( |( r, _) | r. into_mut ( ) )
1082
+ }
1083
+
1084
+ /// Interprets the suffix of the given `bytes` as a `&mut Self` without copying.
1085
+ ///
1086
+ /// `mut_from_suffix` returns a reference to the last `size_of::<Self>()`
1087
+ /// bytes of `bytes`. If `bytes.len() != size_of::<T>()` or the suffix of
1088
+ /// `bytes` is not aligned to `align_of::<T>()`, this returns `None`.
1089
+ ///
1090
+ /// To also access the suffix bytes, use [`Ref::new_from_suffix`]. Then,
1091
+ /// use [`Ref::into_mut`] to get a `&mut Self` with the same lifetime.
1092
+ #[ inline]
1093
+ fn mut_from_suffix ( bytes : & mut [ u8 ] ) -> Option < & mut Self >
1094
+ where
1095
+ Self : Sized + AsBytes ,
1096
+ {
1097
+ Ref :: < & mut [ u8 ] , Self > :: new_from_suffix ( bytes) . map ( |( _, r) | r. into_mut ( ) )
1098
+ }
1099
+
1012
1100
/// Reads a copy of `Self` from `bytes`.
1013
1101
///
1014
1102
/// If `bytes.len() != size_of::<Self>()`, `read_from` returns `None`.
@@ -1017,8 +1105,7 @@ pub unsafe trait FromBytes: FromZeroes {
1017
1105
where
1018
1106
Self : Sized ,
1019
1107
{
1020
- let r = Ref :: < _ , Unalign < Self > > :: new_unaligned ( bytes) ?;
1021
- Some ( r. read ( ) . into_inner ( ) )
1108
+ Ref :: < _ , Unalign < Self > > :: new_unaligned ( bytes) . map ( |r| r. read ( ) . into_inner ( ) )
1022
1109
}
1023
1110
1024
1111
/// Reads a copy of `Self` from the prefix of `bytes`.
@@ -1031,8 +1118,8 @@ pub unsafe trait FromBytes: FromZeroes {
1031
1118
where
1032
1119
Self : Sized ,
1033
1120
{
1034
- let ( r , _suffix ) = Ref :: < _ , Unalign < Self > > :: new_unaligned_from_prefix ( bytes) ? ;
1035
- Some ( r. read ( ) . into_inner ( ) )
1121
+ Ref :: < _ , Unalign < Self > > :: new_unaligned_from_prefix ( bytes)
1122
+ . map ( | ( r , _ ) | r. read ( ) . into_inner ( ) )
1036
1123
}
1037
1124
1038
1125
/// Reads a copy of `Self` from the suffix of `bytes`.
@@ -1045,8 +1132,8 @@ pub unsafe trait FromBytes: FromZeroes {
1045
1132
where
1046
1133
Self : Sized ,
1047
1134
{
1048
- let ( _prefix , r ) = Ref :: < _ , Unalign < Self > > :: new_unaligned_from_suffix ( bytes) ? ;
1049
- Some ( r. read ( ) . into_inner ( ) )
1135
+ Ref :: < _ , Unalign < Self > > :: new_unaligned_from_suffix ( bytes)
1136
+ . map ( | ( _ , r ) | r. read ( ) . into_inner ( ) )
1050
1137
}
1051
1138
}
1052
1139
@@ -4453,6 +4540,69 @@ mod tests {
4453
4540
}
4454
4541
}
4455
4542
4543
+ #[ test]
4544
+ fn test_ref_from_mut_from ( ) {
4545
+ // Test `FromBytes::{ref_from, mut_from}{,_prefix,_suffix}` success cases
4546
+ // Exhaustive coverage for these methods is covered by the `Ref` tests above,
4547
+ // which these helper methods defer to.
4548
+
4549
+ let mut buf =
4550
+ Align :: < [ u8 ; 16 ] , AU64 > :: new ( [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 ] ) ;
4551
+
4552
+ assert_eq ! (
4553
+ AU64 :: ref_from( & buf. t[ 8 ..] ) . unwrap( ) . 0 . to_ne_bytes( ) ,
4554
+ [ 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 ]
4555
+ ) ;
4556
+ let suffix = AU64 :: mut_from ( & mut buf. t [ 8 ..] ) . unwrap ( ) ;
4557
+ suffix. 0 = 0x0101010101010101 ;
4558
+ assert_eq ! ( <[ u8 ; 9 ] >:: ref_from_suffix( & buf. t[ ..] ) . unwrap( ) , & [ 7u8 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ] ) ;
4559
+ let suffix = AU64 :: mut_from_suffix ( & mut buf. t [ 1 ..] ) . unwrap ( ) ;
4560
+ suffix. 0 = 0x0202020202020202 ;
4561
+ <[ u8 ; 10 ] >:: mut_from_suffix ( & mut buf. t [ ..] ) . unwrap ( ) [ 0 ] = 42 ;
4562
+ assert_eq ! ( <[ u8 ; 9 ] >:: ref_from_prefix( & buf. t[ ..] ) . unwrap( ) , & [ 0 , 1 , 2 , 3 , 4 , 5 , 42 , 7 , 2 ] ) ;
4563
+ <[ u8 ; 2 ] >:: mut_from_prefix ( & mut buf. t [ ..] ) . unwrap ( ) [ 1 ] = 30 ;
4564
+ assert_eq ! ( buf. t, [ 0 , 30 , 2 , 3 , 4 , 5 , 42 , 7 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 ] ) ;
4565
+ }
4566
+
4567
+ #[ test]
4568
+ fn test_ref_from_mut_from_error ( ) {
4569
+ // Test `FromBytes::{ref_from, mut_from}{,_prefix,_suffix}` error cases.
4570
+
4571
+ // Fail because the buffer is too large.
4572
+ let mut buf = Align :: < [ u8 ; 16 ] , AU64 > :: default ( ) ;
4573
+ // `buf.t` should be aligned to 8, so only the length check should fail.
4574
+ assert ! ( AU64 :: ref_from( & buf. t[ ..] ) . is_none( ) ) ;
4575
+ assert ! ( AU64 :: mut_from( & mut buf. t[ ..] ) . is_none( ) ) ;
4576
+ assert ! ( <[ u8 ; 8 ] >:: ref_from( & buf. t[ ..] ) . is_none( ) ) ;
4577
+ assert ! ( <[ u8 ; 8 ] >:: mut_from( & mut buf. t[ ..] ) . is_none( ) ) ;
4578
+
4579
+ // Fail because the buffer is too small.
4580
+ let mut buf = Align :: < [ u8 ; 4 ] , AU64 > :: default ( ) ;
4581
+ assert ! ( AU64 :: ref_from( & buf. t[ ..] ) . is_none( ) ) ;
4582
+ assert ! ( AU64 :: mut_from( & mut buf. t[ ..] ) . is_none( ) ) ;
4583
+ assert ! ( <[ u8 ; 8 ] >:: ref_from( & buf. t[ ..] ) . is_none( ) ) ;
4584
+ assert ! ( <[ u8 ; 8 ] >:: mut_from( & mut buf. t[ ..] ) . is_none( ) ) ;
4585
+ assert ! ( AU64 :: ref_from_prefix( & buf. t[ ..] ) . is_none( ) ) ;
4586
+ assert ! ( AU64 :: mut_from_prefix( & mut buf. t[ ..] ) . is_none( ) ) ;
4587
+ assert ! ( AU64 :: ref_from_suffix( & buf. t[ ..] ) . is_none( ) ) ;
4588
+ assert ! ( AU64 :: mut_from_suffix( & mut buf. t[ ..] ) . is_none( ) ) ;
4589
+ assert ! ( <[ u8 ; 8 ] >:: ref_from_prefix( & buf. t[ ..] ) . is_none( ) ) ;
4590
+ assert ! ( <[ u8 ; 8 ] >:: mut_from_prefix( & mut buf. t[ ..] ) . is_none( ) ) ;
4591
+ assert ! ( <[ u8 ; 8 ] >:: ref_from_suffix( & buf. t[ ..] ) . is_none( ) ) ;
4592
+ assert ! ( <[ u8 ; 8 ] >:: mut_from_suffix( & mut buf. t[ ..] ) . is_none( ) ) ;
4593
+
4594
+ // Fail because the alignment is insufficient.
4595
+ let mut buf = Align :: < [ u8 ; 13 ] , AU64 > :: default ( ) ;
4596
+ assert ! ( AU64 :: ref_from( & buf. t[ 1 ..] ) . is_none( ) ) ;
4597
+ assert ! ( AU64 :: mut_from( & mut buf. t[ 1 ..] ) . is_none( ) ) ;
4598
+ assert ! ( AU64 :: ref_from( & buf. t[ 1 ..] ) . is_none( ) ) ;
4599
+ assert ! ( AU64 :: mut_from( & mut buf. t[ 1 ..] ) . is_none( ) ) ;
4600
+ assert ! ( AU64 :: ref_from_prefix( & buf. t[ 1 ..] ) . is_none( ) ) ;
4601
+ assert ! ( AU64 :: mut_from_prefix( & mut buf. t[ 1 ..] ) . is_none( ) ) ;
4602
+ assert ! ( AU64 :: ref_from_suffix( & buf. t[ ..] ) . is_none( ) ) ;
4603
+ assert ! ( AU64 :: mut_from_suffix( & mut buf. t[ ..] ) . is_none( ) ) ;
4604
+ }
4605
+
4456
4606
#[ test]
4457
4607
#[ allow( clippy:: cognitive_complexity) ]
4458
4608
fn test_new_error ( ) {
0 commit comments