44
55use super :: { AllocError , Flags } ;
66use alloc:: boxed:: Box ;
7- use core:: mem:: MaybeUninit ;
7+ use core:: { mem:: MaybeUninit , ptr , result :: Result } ;
88
99/// Extensions to [`Box`].
1010pub trait BoxExt < T > : Sized {
@@ -17,6 +17,22 @@ pub trait BoxExt<T>: Sized {
1717 ///
1818 /// The allocation may fail, in which case an error is returned.
1919 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 > > ;
2036}
2137
2238impl < T > BoxExt < T > for Box < T > {
@@ -53,4 +69,17 @@ impl<T> BoxExt<T> for Box<T> {
5369 // zero-sized types, we use `NonNull::dangling`.
5470 Ok ( unsafe { Box :: from_raw ( ptr) } )
5571 }
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+ }
5685}
0 commit comments