2
2
3
3
use crate :: ResultExt ;
4
4
use crate :: { Result , Status } ;
5
- use :: alloc:: { alloc , boxed:: Box } ;
5
+ use :: alloc:: boxed:: Box ;
6
6
use core:: alloc:: Layout ;
7
7
use core:: fmt:: Debug ;
8
8
use core:: slice;
9
9
use uefi:: data_types:: Align ;
10
10
use uefi:: Error ;
11
11
12
+ #[ cfg( not( feature = "unstable" ) ) ]
13
+ use :: alloc:: alloc:: { alloc, dealloc} ;
14
+
15
+ #[ cfg( feature = "unstable" ) ]
16
+ use { core:: alloc:: Allocator , core:: ptr:: NonNull } ;
17
+
12
18
/// Helper to return owned versions of certain UEFI data structures on the heap in a [`Box`]. This
13
19
/// function is intended to wrap low-level UEFI functions of this crate that
14
20
/// - can consume an empty buffer without a panic to get the required buffer size in the errors
@@ -17,12 +23,24 @@ use uefi::Error;
17
23
/// buffer size is sufficient, and
18
24
/// - return a mutable typed reference that points to the same memory as the input buffer on
19
25
/// success.
20
- pub fn make_boxed <
26
+ ///
27
+ /// # Feature `unstable` / `allocator_api`
28
+ /// By default, this function works with Rust's default allocation mechanism. If you activate the
29
+ /// `unstable`-feature, it uses the `allocator_api` instead. In that case, the function takes an
30
+ /// additional parameter describing the specific [`Allocator`]. You can use [`alloc::alloc::Global`]
31
+ /// as default.
32
+ pub ( crate ) fn make_boxed <
21
33
' a ,
34
+ // The UEFI data structure.
22
35
Data : Align + ?Sized + Debug + ' a ,
23
36
F : FnMut ( & ' a mut [ u8 ] ) -> Result < & ' a mut Data , Option < usize > > ,
37
+ #[ cfg( feature = "unstable" ) ] A : Allocator ,
24
38
> (
39
+ // A function to read the UEFI data structure into a provided buffer.
25
40
mut fetch_data_fn : F ,
41
+ #[ cfg( feature = "unstable" ) ]
42
+ // Allocator of the `allocator_api` feature. You can use `Global` as default.
43
+ allocator : A ,
26
44
) -> Result < Box < Data > > {
27
45
let required_size = match fetch_data_fn ( & mut [ ] ) . map_err ( Error :: split) {
28
46
// This is the expected case: the empty buffer passed in is too
@@ -40,13 +58,23 @@ pub fn make_boxed<
40
58
. unwrap ( )
41
59
. pad_to_align ( ) ;
42
60
43
- // Allocate the buffer.
44
- let heap_buf: * mut u8 = unsafe {
45
- let ptr = alloc:: alloc ( layout) ;
46
- if ptr. is_null ( ) {
47
- return Err ( Status :: OUT_OF_RESOURCES . into ( ) ) ;
61
+ // Allocate the buffer on the heap.
62
+ let heap_buf: * mut u8 = {
63
+ #[ cfg( not( feature = "unstable" ) ) ]
64
+ {
65
+ let ptr = unsafe { alloc ( layout) } ;
66
+ if ptr. is_null ( ) {
67
+ return Err ( Status :: OUT_OF_RESOURCES . into ( ) ) ;
68
+ }
69
+ ptr
48
70
}
49
- ptr
71
+
72
+ #[ cfg( feature = "unstable" ) ]
73
+ allocator
74
+ . allocate ( layout)
75
+ . map_err ( |_| <Status as Into < Error > >:: into ( Status :: OUT_OF_RESOURCES ) ) ?
76
+ . as_ptr ( )
77
+ . cast :: < u8 > ( )
50
78
} ;
51
79
52
80
// Read the data into the provided buffer.
@@ -59,7 +87,14 @@ pub fn make_boxed<
59
87
let data: & mut Data = match data {
60
88
Ok ( data) => data,
61
89
Err ( err) => {
62
- unsafe { alloc:: dealloc ( heap_buf, layout) } ;
90
+ #[ cfg( not( feature = "unstable" ) ) ]
91
+ unsafe {
92
+ dealloc ( heap_buf, layout)
93
+ } ;
94
+ #[ cfg( feature = "unstable" ) ]
95
+ unsafe {
96
+ allocator. deallocate ( NonNull :: new ( heap_buf) . unwrap ( ) , layout)
97
+ }
63
98
return Err ( err) ;
64
99
}
65
100
} ;
@@ -73,6 +108,8 @@ pub fn make_boxed<
73
108
mod tests {
74
109
use super :: * ;
75
110
use crate :: ResultExt ;
111
+ #[ cfg( feature = "unstable" ) ]
112
+ use alloc:: alloc:: Global ;
76
113
use core:: mem:: { align_of, size_of} ;
77
114
78
115
/// Some simple dummy type to test [`make_boxed`].
@@ -166,14 +203,27 @@ mod tests {
166
203
assert_eq ! ( & data. 0 . 0 , & [ 1 , 2 , 3 , 4 ] ) ;
167
204
}
168
205
206
+ /// This unit tests checks the [`make_boxed`] utility. The test has different code and behavior
207
+ /// depending on whether the "unstable" feature is active or not.
169
208
#[ test]
170
209
fn test_make_boxed_utility ( ) {
171
210
let fetch_data_fn = |buf| uefi_function_stub_read ( buf) ;
211
+
212
+ #[ cfg( not( feature = "unstable" ) ) ]
172
213
let data: Box < SomeData > = make_boxed ( fetch_data_fn) . unwrap ( ) ;
214
+
215
+ #[ cfg( feature = "unstable" ) ]
216
+ let data: Box < SomeData > = make_boxed ( fetch_data_fn, Global ) . unwrap ( ) ;
173
217
assert_eq ! ( & data. 0 , & [ 1 , 2 , 3 , 4 ] ) ;
174
218
175
219
let fetch_data_fn = |buf| uefi_function_stub_read ( buf) ;
220
+
221
+ #[ cfg( not( feature = "unstable" ) ) ]
176
222
let data: Box < SomeDataAlign16 > = make_boxed ( fetch_data_fn) . unwrap ( ) ;
223
+
224
+ #[ cfg( feature = "unstable" ) ]
225
+ let data: Box < SomeDataAlign16 > = make_boxed ( fetch_data_fn, Global ) . unwrap ( ) ;
226
+
177
227
assert_eq ! ( & data. 0 . 0 , & [ 1 , 2 , 3 , 4 ] ) ;
178
228
}
179
229
}
0 commit comments