4
4
5
5
use super :: { AllocError , Flags } ;
6
6
use alloc:: boxed:: Box ;
7
- use core:: mem:: MaybeUninit ;
7
+ use core:: { mem:: MaybeUninit , ptr , result :: Result } ;
8
8
9
9
/// Extensions to [`Box`].
10
10
pub trait BoxExt < T > : Sized {
@@ -17,6 +17,22 @@ pub trait BoxExt<T>: Sized {
17
17
///
18
18
/// The allocation may fail, in which case an error is returned.
19
19
fn new_uninit ( flags : Flags ) -> Result < Box < MaybeUninit < T > > , AllocError > ;
20
+
21
+ /// Drops the contents, but keeps the allocation.
22
+ ///
23
+ /// # Examples
24
+ ///
25
+ /// ```
26
+ /// use kernel::alloc::{flags, box_ext::BoxExt};
27
+ /// let value = Box::new([0; 32], flags::GFP_KERNEL)?;
28
+ /// assert_eq!(*value, [0; 32]);
29
+ /// let value = Box::drop_contents(value);
30
+ /// // Now we can re-use `value`:
31
+ /// let value = Box::write(value, [1; 32]);
32
+ /// assert_eq!(*value, [1; 32]);
33
+ /// # Ok::<(), Error>(())
34
+ /// ```
35
+ fn drop_contents ( this : Self ) -> Box < MaybeUninit < T > > ;
20
36
}
21
37
22
38
impl < T > BoxExt < T > for Box < T > {
@@ -53,4 +69,17 @@ impl<T> BoxExt<T> for Box<T> {
53
69
// zero-sized types, we use `NonNull::dangling`.
54
70
Ok ( unsafe { Box :: from_raw ( ptr) } )
55
71
}
72
+
73
+ fn drop_contents ( this : Self ) -> Box < MaybeUninit < T > > {
74
+ let ptr = Box :: into_raw ( this) ;
75
+ // SAFETY: `ptr` is valid, because it came from `Box::into_raw`.
76
+ unsafe { ptr:: drop_in_place ( ptr) } ;
77
+
78
+ // CAST: `MaybeUninit<T>` is a transparent wrapper of `T`.
79
+ let ptr = ptr. cast :: < MaybeUninit < T > > ( ) ;
80
+
81
+ // SAFETY: `ptr` is valid for writes, because it came from `Box::into_raw` and it is valid for
82
+ // reads, since the pointer came from `Box::into_raw` and the type is `MaybeUninit<T>`.
83
+ unsafe { Box :: from_raw ( ptr) }
84
+ }
56
85
}
0 commit comments