moveit/new/
mod.rs

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//! In-place constructors.
16//!
17//! This module provides a range of helpers such as [`new::by()`] and
18//! [`new::from()`] for creating constructors. It is preferred style to
19//! `use moveit::new;` and refer to these helpers with a `new::` prefix.
20
21use core::convert::Infallible;
22use core::mem::MaybeUninit;
23use core::ops::Deref;
24use core::pin::Pin;
25
26#[cfg(doc)]
27use {crate::new, core::ops::DerefMut};
28
29use alloc::{boxed::Box, rc::Rc, sync::Arc};
30
31mod copy_new;
32mod factories;
33mod move_new;
34
35mod impls;
36
37pub use copy_new::*;
38pub use factories::*;
39pub use move_new::*;
40
41/// An in-place constructor for a particular type.
42///
43/// # Safety
44///
45/// [`New::new()`] must leave its destination argument in a valid, initialized
46/// state.
47#[must_use = "`New`s do nothing until emplaced into storage"]
48pub unsafe trait New: Sized {
49  /// The type to construct.
50  type Output;
51  /// Construct a new value using the arguments stored in `self`.
52  ///
53  /// # Safety
54  ///
55  /// `this` must be freshly-created memory; this function must not
56  /// be used to mutate a previously-pinned pointer that has had `self: Pin`
57  /// functions called on it.
58  unsafe fn new(self, this: Pin<&mut MaybeUninit<Self::Output>>);
59
60  /// Adds a post-construction operation.
61  ///
62  /// This function wraps `self` in an another [`New`] type which will call
63  /// `post` once the main emplacement operation is complete. This is most
64  /// useful for the case where creation of the value itself does not depend
65  /// on the final address, but where some address-sensitive setup may want
66  /// to occur; this can help minimize the scope (or even need for) `unsafe`.
67  ///
68  /// This function is best combined with other helpers:
69  ///
70  /// ```
71  /// # use moveit::{new, moveit, New};
72  /// # use std::pin::Pin;
73  /// pub struct MyType { /* ... */ }
74  ///
75  /// impl MyType {
76  ///   pub fn new() -> impl New<Output = Self> {
77  ///     new::of(MyType { /* ... */ }).with(|this| {
78  ///       // Address-sensitive setup can occur here.
79  ///     })
80  ///   }
81  /// }
82  /// ```
83  ///
84  /// Note: The return value of this function should not be relied upon; a
85  /// future version will replace it with `impl New`.
86  fn with<F>(self, post: F) -> With<Self, F>
87  where
88    F: FnOnce(Pin<&mut Self::Output>),
89  {
90    With(self, post)
91  }
92}
93
94/// An in-place constructor for a particular type, which can potentially fail.
95///
96/// Emplacing a `TryNew` may allocate even when construction fails; prefer to
97/// use `Result<impl New>` when possible, instead.
98///
99/// # Safety
100///
101/// [`TryNew::try_new()`] must leave its destination argument in a valid,
102/// initialized state when it returns `Ok`.
103#[must_use = "`New`s do nothing until emplaced into storage"]
104pub unsafe trait TryNew: Sized {
105  /// The type to construct.
106  type Output;
107  /// The error the construction operation may return.
108  type Error;
109  /// Try to construct a new value using the arguments stored in `self`.
110  ///
111  /// # Safety
112  ///
113  /// `this` must be freshly-created memory; this function must not
114  /// be used to mutate a previously-pinned pointer that has had `self: Pin`
115  /// functions called on it.
116  unsafe fn try_new(
117    self,
118    this: Pin<&mut MaybeUninit<Self::Output>>,
119  ) -> Result<(), Self::Error>;
120
121  /// Adds a post-construction operation.
122  ///
123  /// This function is analogous to [`New::with()`]; see its documentation for
124  /// more information.
125  ///
126  /// Note: The return value of this function should not be relied upon; a
127  /// future version will replace it with `impl TryNew`.
128  fn with<F>(self, post: F) -> TryWith<Self, F> {
129    TryWith(self, post)
130  }
131}
132
133unsafe impl<N: New> TryNew for N {
134  type Output = N::Output;
135  type Error = Infallible;
136  unsafe fn try_new(
137    self,
138    this: Pin<&mut MaybeUninit<Self::Output>>,
139  ) -> Result<(), Self::Error> {
140    self.new(this);
141    Ok(())
142  }
143}
144
145/// A pointer type that may be "emplaced" as a stable address which a [`New`] may be used to
146/// construct a value with.
147///
148/// The `Emplace<T>::Output` type is usually either `Self` or `Pin<Self>` depending on the API of
149/// `Self` with respect to [`DerefMut`].
150///
151/// For example, `Arc<T>`, `Box<T>`, and `Rc<T>` are all `Emplace<T, Output = Pin<Self>>`.
152///
153/// However, `cxx::UniquePtr<T>: Emplace<T, Output = Self>`, since `cxx::UniquePtr<T>` already only
154/// allows obtaining pinned mutable references to `T` due to its more restrictive API, and hence
155/// `cxx::UniquePtr<T>` does not need to be pinned itself.
156pub trait Emplace<T>: Sized + Deref {
157  /// The stable address type within which a value of type `T` is emplaced.
158  type Output: Deref<Target = Self::Target>;
159
160  /// Constructs a new smart pointer and emplaces `n` into its storage.
161  fn emplace<N: New<Output = T>>(n: N) -> Self::Output {
162    match Self::try_emplace(n) {
163      Ok(x) => x,
164      Err(e) => match e {},
165    }
166  }
167
168  /// Constructs a new smart pointer and tries to emplace `n` into its storage.
169  fn try_emplace<N: TryNew<Output = T>>(n: N)
170    -> Result<Self::Output, N::Error>;
171}
172
173impl<T> Emplace<T> for Box<T> {
174  type Output = Pin<Self>;
175
176  fn try_emplace<N: TryNew<Output = T>>(
177    n: N,
178  ) -> Result<Self::Output, N::Error> {
179    let mut uninit = Box::new(MaybeUninit::<T>::uninit());
180    unsafe {
181      let pinned = Pin::new_unchecked(&mut *uninit);
182      n.try_new(pinned)?;
183      Ok(Pin::new_unchecked(Box::from_raw(
184        Box::into_raw(uninit).cast::<T>(),
185      )))
186    }
187  }
188}
189
190impl<T> Emplace<T> for Rc<T> {
191  type Output = Pin<Self>;
192
193  fn try_emplace<N: TryNew<Output = T>>(
194    n: N,
195  ) -> Result<Self::Output, N::Error> {
196    let uninit = Rc::new(MaybeUninit::<T>::uninit());
197    unsafe {
198      let pinned = Pin::new_unchecked(&mut *(Rc::as_ptr(&uninit) as *mut _));
199      n.try_new(pinned)?;
200      Ok(Pin::new_unchecked(Rc::from_raw(
201        Rc::into_raw(uninit).cast::<T>(),
202      )))
203    }
204  }
205}
206
207impl<T> Emplace<T> for Arc<T> {
208  type Output = Pin<Self>;
209
210  fn try_emplace<N: TryNew<Output = T>>(
211    n: N,
212  ) -> Result<Self::Output, N::Error> {
213    let uninit = Arc::new(MaybeUninit::<T>::uninit());
214    unsafe {
215      let pinned = Pin::new_unchecked(&mut *(Arc::as_ptr(&uninit) as *mut _));
216      n.try_new(pinned)?;
217      Ok(Pin::new_unchecked(Arc::from_raw(
218        Arc::into_raw(uninit).cast::<T>(),
219      )))
220    }
221  }
222}
223
224#[doc(hidden)]
225pub struct With<N, F>(N, F);
226
227unsafe impl<N: New, F> New for With<N, F>
228where
229  F: FnOnce(Pin<&mut N::Output>),
230{
231  type Output = N::Output;
232  #[inline]
233  unsafe fn new(self, mut this: Pin<&mut MaybeUninit<Self::Output>>) {
234    self.0.new(this.as_mut());
235    // Now that `new()` has returned, we can assume `this` is initialized.
236    let this = this.map_unchecked_mut(|x| x.assume_init_mut());
237    (self.1)(this)
238  }
239}
240
241#[doc(hidden)]
242pub struct TryWith<N, F>(N, F);
243
244unsafe impl<N: TryNew, F> TryNew for TryWith<N, F>
245where
246  F: FnOnce(Pin<&mut N::Output>) -> Result<(), N::Error>,
247{
248  type Output = N::Output;
249  type Error = N::Error;
250  #[inline]
251  unsafe fn try_new(
252    self,
253    mut this: Pin<&mut MaybeUninit<Self::Output>>,
254  ) -> Result<(), Self::Error> {
255    self.0.try_new(this.as_mut())?;
256    // Now that `new()` has returned, we can assume `this` is initialized.
257    let this = this.map_unchecked_mut(|x| x.assume_init_mut());
258    (self.1)(this)
259  }
260}
261
262/// A swappable type, which is able to efficiently swap the contents of two of
263/// its values.
264///
265/// Unlike [`New`], `Swap` is safe, because it does not impose any requirements
266/// on the swapped pointers.
267///
268/// It is possible to implement swapping with a source type that isn't `Self`.
269pub trait Swap<Rhs = Self> {
270  /// Swaps the contents of `self` and `src` without running any destructors.
271  fn swap_with(self: Pin<&mut Self>, src: Pin<&mut Rhs>);
272}