moveit/
alloc_support.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Support for the `alloc` crate, when available.

use core::mem::MaybeUninit;
use core::pin::Pin;

use alloc::boxed::Box;

use crate::move_ref::MoveRef;
use crate::move_ref::{AsMove, DerefMove};
use crate::slot::DroppingSlot;

impl<T> AsMove for Box<T> {
  type Storage = Box<MaybeUninit<T>>;

  #[inline]
  fn as_move<'frame>(
    self,
    storage: DroppingSlot<'frame, Self::Storage>,
  ) -> Pin<MoveRef<'frame, Self::Target>>
  where
    Self: 'frame,
  {
    MoveRef::into_pin(self.deref_move(storage))
  }
}

unsafe impl<T> DerefMove for Box<T> {
  #[inline]
  fn deref_move<'frame>(
    self,
    storage: DroppingSlot<'frame, Self::Storage>,
  ) -> MoveRef<'frame, Self::Target>
  where
    Self: 'frame,
  {
    let cast =
      unsafe { Box::from_raw(Box::into_raw(self).cast::<MaybeUninit<T>>()) };

    let (storage, drop_flag) = storage.put(cast);
    unsafe { MoveRef::new_unchecked(storage.assume_init_mut(), drop_flag) }
  }
}

#[cfg(test)]
mod tests {
  use crate::move_ref::test::Immovable;
  use crate::moveit;
  use crate::new::mov;
  use crate::Emplace;

  #[test]
  fn test_mov_box() {
    let foo = Box::emplace(Immovable::new());
    moveit!(let _foo = mov(foo));
  }
}