@@ -75,6 +75,7 @@ mod tests {
7575 use crate :: ResultExt ;
7676 use core:: mem:: { align_of, size_of} ;
7777
78+ /// Some simple dummy type to test [`make_boxed`].
7879 #[ derive( Debug ) ]
7980 #[ repr( C ) ]
8081 struct SomeData ( [ u8 ; 4 ] ) ;
@@ -85,53 +86,94 @@ mod tests {
8586 }
8687 }
8788
89+ /// Type wrapper that ensures an alignment of 16 for the underlying data.
90+ #[ derive( Debug ) ]
91+ #[ repr( C , align( 16 ) ) ]
92+ struct Align16 < T > ( T ) ;
93+
94+ /// Version of [`SomeData`] that has an alignment of 16.
95+ type SomeDataAlign16 = Align16 < SomeData > ;
96+
97+ impl Align for SomeDataAlign16 {
98+ fn alignment ( ) -> usize {
99+ align_of :: < Self > ( )
100+ }
101+ }
102+
88103 /// Function that behaves like the other UEFI functions. It takes a
89104 /// mutable reference to a buffer memory that represents a [`SomeData`]
90105 /// instance.
91- fn uefi_function_stub_read ( buf : & mut [ u8 ] ) -> Result < & mut SomeData , Option < usize > > {
92- if buf. len ( ) < 4 {
93- return Status :: BUFFER_TOO_SMALL . into_with ( || panic ! ( ) , |_| Some ( 4 ) ) ;
106+ fn uefi_function_stub_read < Data : Align > ( buf : & mut [ u8 ] ) -> Result < & mut Data , Option < usize > > {
107+ let required_size = size_of :: < Data > ( ) ;
108+
109+ if buf. len ( ) < required_size {
110+ // We can use an zero-length buffer to find the required size.
111+ return Status :: BUFFER_TOO_SMALL . into_with ( || panic ! ( ) , |_| Some ( required_size) ) ;
94112 } ;
95113
114+ // assert alignment
115+ assert_eq ! (
116+ buf. as_ptr( ) as usize % Data :: alignment( ) ,
117+ 0 ,
118+ "The buffer must be correctly aligned!"
119+ ) ;
120+
96121 buf[ 0 ] = 1 ;
97122 buf[ 1 ] = 2 ;
98123 buf[ 2 ] = 3 ;
99124 buf[ 3 ] = 4 ;
100125
101- let data = unsafe { & mut * buf. as_mut_ptr ( ) . cast :: < SomeData > ( ) } ;
126+ let data = unsafe { & mut * buf. as_mut_ptr ( ) . cast :: < Data > ( ) } ;
102127
103128 Ok ( data)
104129 }
105130
106- // Some basic checks so that miri reports everything is fine.
131+ // Some basic sanity checks so that we can catch problems early that miri would detect
132+ // otherwise.
107133 #[ test]
108- fn some_data_type_size_constraints ( ) {
134+ fn test_some_data_type_size_constraints ( ) {
109135 assert_eq ! ( size_of:: <SomeData >( ) , 4 ) ;
110- assert_eq ! ( align_of:: <SomeData >( ) , 1 ) ;
136+ assert_eq ! ( SomeData :: alignment( ) , 1 ) ;
137+ assert_eq ! (
138+ size_of:: <SomeDataAlign16 >( ) ,
139+ 16 ,
140+ "The size must be 16 instead of 4, as in Rust the runtime size is a multiple of the alignment."
141+ ) ;
142+ assert_eq ! ( SomeDataAlign16 :: alignment( ) , 16 ) ;
111143 }
112144
145+ // Tests `uefi_function_stub_read` which is the foundation for the `test_make_boxed_utility`
146+ // test.
113147 #[ test]
114- fn basic_stub_read ( ) {
148+ fn test_basic_stub_read ( ) {
115149 assert_eq ! (
116- uefi_function_stub_read( & mut [ ] ) . status( ) ,
150+ uefi_function_stub_read:: < SomeData > ( & mut [ ] ) . status( ) ,
117151 Status :: BUFFER_TOO_SMALL
118152 ) ;
119153 assert_eq ! (
120- * uefi_function_stub_read( & mut [ ] ) . unwrap_err( ) . data( ) ,
154+ * uefi_function_stub_read:: <SomeData >( & mut [ ] )
155+ . unwrap_err( )
156+ . data( ) ,
121157 Some ( 4 )
122158 ) ;
123159
124160 let mut buf: [ u8 ; 4 ] = [ 0 ; 4 ] ;
125- let data = uefi_function_stub_read ( & mut buf) . unwrap ( ) ;
161+ let data: & mut SomeData = uefi_function_stub_read ( & mut buf) . unwrap ( ) ;
162+ assert_eq ! ( & data. 0 , & [ 1 , 2 , 3 , 4 ] ) ;
126163
127- assert_eq ! ( & data. 0 , & [ 1 , 2 , 3 , 4 ] )
164+ let mut buf: Align16 < [ u8 ; 16 ] > = Align16 ( [ 0 ; 16 ] ) ;
165+ let data: & mut SomeDataAlign16 = uefi_function_stub_read ( & mut buf. 0 ) . unwrap ( ) ;
166+ assert_eq ! ( & data. 0 . 0 , & [ 1 , 2 , 3 , 4 ] ) ;
128167 }
129168
130169 #[ test]
131- fn make_boxed_utility ( ) {
170+ fn test_make_boxed_utility ( ) {
132171 let fetch_data_fn = |buf| uefi_function_stub_read ( buf) ;
133172 let data: Box < SomeData > = make_boxed ( fetch_data_fn) . unwrap ( ) ;
173+ assert_eq ! ( & data. 0 , & [ 1 , 2 , 3 , 4 ] ) ;
134174
135- assert_eq ! ( & data. 0 , & [ 1 , 2 , 3 , 4 ] )
175+ let fetch_data_fn = |buf| uefi_function_stub_read ( buf) ;
176+ let data: Box < SomeDataAlign16 > = make_boxed ( fetch_data_fn) . unwrap ( ) ;
177+ assert_eq ! ( & data. 0 . 0 , & [ 1 , 2 , 3 , 4 ] ) ;
136178 }
137179}
0 commit comments