@@ -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,94 @@ 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 early that miri would detect
132
+ // otherwise.
107
133
#[ test]
108
- fn some_data_type_size_constraints ( ) {
134
+ fn test_some_data_type_size_constraints ( ) {
109
135
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 ) ;
111
143
}
112
144
145
+ // Tests `uefi_function_stub_read` which is the foundation for the `test_make_boxed_utility`
146
+ // test.
113
147
#[ test]
114
- fn basic_stub_read ( ) {
148
+ fn test_basic_stub_read ( ) {
115
149
assert_eq ! (
116
- uefi_function_stub_read( & mut [ ] ) . status( ) ,
150
+ uefi_function_stub_read:: < SomeData > ( & mut [ ] ) . status( ) ,
117
151
Status :: BUFFER_TOO_SMALL
118
152
) ;
119
153
assert_eq ! (
120
- * uefi_function_stub_read( & mut [ ] ) . unwrap_err( ) . data( ) ,
154
+ * uefi_function_stub_read:: <SomeData >( & mut [ ] )
155
+ . unwrap_err( )
156
+ . data( ) ,
121
157
Some ( 4 )
122
158
) ;
123
159
124
160
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 ] ) ;
126
163
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 ] ) ;
128
167
}
129
168
130
169
#[ test]
131
- fn make_boxed_utility ( ) {
170
+ fn test_make_boxed_utility ( ) {
132
171
let fetch_data_fn = |buf| uefi_function_stub_read ( buf) ;
133
172
let data: Box < SomeData > = make_boxed ( fetch_data_fn) . unwrap ( ) ;
173
+ assert_eq ! ( & data. 0 , & [ 1 , 2 , 3 , 4 ] ) ;
134
174
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 ] ) ;
136
178
}
137
179
}
0 commit comments