1 // Copyright 2021 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 //! Support for the `alloc` crate, when available.
16 
17 use core::mem::MaybeUninit;
18 use core::pin::Pin;
19 
20 use alloc::boxed::Box;
21 
22 use crate::move_ref::MoveRef;
23 use crate::move_ref::{AsMove, DerefMove};
24 use crate::slot::DroppingSlot;
25 
26 impl<T> AsMove for Box<T> {
27   type Storage = Box<MaybeUninit<T>>;
28 
29   #[inline]
as_move<'frame>( self, storage: DroppingSlot<'frame, Self::Storage>, ) -> Pin<MoveRef<'frame, Self::Target>> where Self: 'frame,30   fn as_move<'frame>(
31     self,
32     storage: DroppingSlot<'frame, Self::Storage>,
33   ) -> Pin<MoveRef<'frame, Self::Target>>
34   where
35     Self: 'frame,
36   {
37     MoveRef::into_pin(self.deref_move(storage))
38   }
39 }
40 
41 unsafe impl<T> DerefMove for Box<T> {
42   #[inline]
deref_move<'frame>( self, storage: DroppingSlot<'frame, Self::Storage>, ) -> MoveRef<'frame, Self::Target> where Self: 'frame,43   fn deref_move<'frame>(
44     self,
45     storage: DroppingSlot<'frame, Self::Storage>,
46   ) -> MoveRef<'frame, Self::Target>
47   where
48     Self: 'frame,
49   {
50     let cast =
51       unsafe { Box::from_raw(Box::into_raw(self).cast::<MaybeUninit<T>>()) };
52 
53     let (storage, drop_flag) = storage.put(cast);
54     unsafe { MoveRef::new_unchecked(storage.assume_init_mut(), drop_flag) }
55   }
56 }
57 
58 #[cfg(test)]
59 mod tests {
60   use crate::move_ref::test::Immovable;
61   use crate::moveit;
62   use crate::new::mov;
63   use crate::Emplace;
64 
65   #[test]
test_mov_box()66   fn test_mov_box() {
67     let foo = Box::emplace(Immovable::new());
68     moveit!(let _foo = mov(foo));
69   }
70 }
71