@@ -75,6 +75,7 @@ mod tests {
75
75
use crate :: ResultExt ;
76
76
use core:: mem:: { align_of, size_of} ;
77
77
78
+ /// Some simple dummy type to test [`make_boxed`].
78
79
#[ derive( Debug ) ]
79
80
#[ repr( C ) ]
80
81
struct SomeData ( [ u8 ; 4 ] ) ;
@@ -85,53 +86,93 @@ mod tests {
85
86
}
86
87
}
87
88
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
+
88
103
/// Function that behaves like the other UEFI functions. It takes a
89
104
/// mutable reference to a buffer memory that represents a [`SomeData`]
90
105
/// 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) ) ;
94
112
} ;
95
113
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
+
96
121
buf[ 0 ] = 1 ;
97
122
buf[ 1 ] = 2 ;
98
123
buf[ 2 ] = 3 ;
99
124
buf[ 3 ] = 4 ;
100
125
101
- let data = unsafe { & mut * buf. as_mut_ptr ( ) . cast :: < SomeData > ( ) } ;
126
+ let data = unsafe { & mut * buf. as_mut_ptr ( ) . cast :: < Data > ( ) } ;
102
127
103
128
Ok ( data)
104
129
}
105
130
106
- // Some basic checks so that miri reports everything is fine .
131
+ // Some basic sanity checks so that we can catch problems that miri would detect early .
107
132
#[ test]
108
- fn some_data_type_size_constraints ( ) {
133
+ fn test_some_data_type_size_constraints ( ) {
109
134
assert_eq ! ( size_of:: <SomeData >( ) , 4 ) ;
110
- assert_eq ! ( align_of:: <SomeData >( ) , 1 ) ;
135
+ assert_eq ! ( SomeData :: alignment( ) , 1 ) ;
136
+ assert_eq ! (
137
+ size_of:: <SomeDataAlign16 >( ) ,
138
+ 16 ,
139
+ "The size must be 16 instead of 4, as in Rust the runtime size is a multiple of the alignment."
140
+ ) ;
141
+ assert_eq ! ( SomeDataAlign16 :: alignment( ) , 16 ) ;
111
142
}
112
143
144
+ // Tests `uefi_function_stub_read` which is the foundation for the `test_make_boxed_utility`
145
+ // test.
113
146
#[ test]
114
- fn basic_stub_read ( ) {
147
+ fn test_basic_stub_read ( ) {
115
148
assert_eq ! (
116
- uefi_function_stub_read( & mut [ ] ) . status( ) ,
149
+ uefi_function_stub_read:: < SomeData > ( & mut [ ] ) . status( ) ,
117
150
Status :: BUFFER_TOO_SMALL
118
151
) ;
119
152
assert_eq ! (
120
- * uefi_function_stub_read( & mut [ ] ) . unwrap_err( ) . data( ) ,
153
+ * uefi_function_stub_read:: <SomeData >( & mut [ ] )
154
+ . unwrap_err( )
155
+ . data( ) ,
121
156
Some ( 4 )
122
157
) ;
123
158
124
159
let mut buf: [ u8 ; 4 ] = [ 0 ; 4 ] ;
125
- let data = uefi_function_stub_read ( & mut buf) . unwrap ( ) ;
160
+ let data: & mut SomeData = uefi_function_stub_read ( & mut buf) . unwrap ( ) ;
161
+ assert_eq ! ( & data. 0 , & [ 1 , 2 , 3 , 4 ] ) ;
126
162
127
- assert_eq ! ( & data. 0 , & [ 1 , 2 , 3 , 4 ] )
163
+ let mut buf: Align16 < [ u8 ; 16 ] > = Align16 ( [ 0 ; 16 ] ) ;
164
+ let data: & mut SomeDataAlign16 = uefi_function_stub_read ( & mut buf. 0 ) . unwrap ( ) ;
165
+ assert_eq ! ( & data. 0 . 0 , & [ 1 , 2 , 3 , 4 ] ) ;
128
166
}
129
167
130
168
#[ test]
131
- fn make_boxed_utility ( ) {
169
+ fn test_make_boxed_utility ( ) {
132
170
let fetch_data_fn = |buf| uefi_function_stub_read ( buf) ;
133
171
let data: Box < SomeData > = make_boxed ( fetch_data_fn) . unwrap ( ) ;
172
+ assert_eq ! ( & data. 0 , & [ 1 , 2 , 3 , 4 ] ) ;
134
173
135
- assert_eq ! ( & data. 0 , & [ 1 , 2 , 3 , 4 ] )
174
+ let fetch_data_fn = |buf| uefi_function_stub_read ( buf) ;
175
+ let data: Box < SomeDataAlign16 > = make_boxed ( fetch_data_fn) . unwrap ( ) ;
176
+ assert_eq ! ( & data. 0 . 0 , & [ 1 , 2 , 3 , 4 ] ) ;
136
177
}
137
178
}
0 commit comments