blob: e0f4da031c5551f177bbd171a12482759825f168 [file] [log] [blame]
// 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.
//! In-place constructors.
//!
//! This module provides a range of helpers such as [`new::by()`] and
//! [`new::from()`] for creating constructors. It is preferred style to
//! `use moveit::new;` and refer to these helpers with a `new::` prefix.
use core::convert::Infallible;
use core::mem::MaybeUninit;
use core::ops::Deref;
use core::pin::Pin;
#[cfg(doc)]
use {crate::new, core::ops::DerefMut};
use alloc::{boxed::Box, rc::Rc, sync::Arc};
mod copy_new;
mod factories;
mod move_new;
mod impls;
pub use copy_new::*;
pub use factories::*;
pub use move_new::*;
/// An in-place constructor for a particular type.
///
/// # Safety
///
/// [`New::new()`] must leave its destination argument in a valid, initialized
/// state.
#[must_use = "`New`s do nothing until emplaced into storage"]
pub unsafe trait New: Sized {
/// The type to construct.
type Output;
/// Construct a new value using the arguments stored in `self`.
///
/// # Safety
///
/// `this` must be freshly-created memory; this function must not
/// be used to mutate a previously-pinned pointer that has had `self: Pin`
/// functions called on it.
unsafe fn new(self, this: Pin<&mut MaybeUninit<Self::Output>>);
/// Adds a post-construction operation.
///
/// This function wraps `self` in an another [`New`] type which will call
/// `post` once the main emplacement operation is complete. This is most
/// useful for the case where creation of the value itself does not depend
/// on the final address, but where some address-sensitive setup may want
/// to occur; this can help minimize the scope (or even need for) `unsafe`.
///
/// This function is best combined with other helpers:
///
/// ```
/// # use moveit::{new, moveit, New};
/// # use std::pin::Pin;
/// pub struct MyType { /* ... */ }
///
/// impl MyType {
/// pub fn new() -> impl New<Output = Self> {
/// new::of(MyType { /* ... */ }).with(|this| {
/// // Address-sensitive setup can occur here.
/// })
/// }
/// }
/// ```
///
/// Note: The return value of this function should not be relied upon; a
/// future version will replace it with `impl New`.
fn with<F>(self, post: F) -> With<Self, F>
where
F: FnOnce(Pin<&mut Self::Output>),
{
With(self, post)
}
}
/// An in-place constructor for a particular type, which can potentially fail.
///
/// Emplacing a `TryNew` may allocate even when construction fails; prefer to
/// use `Result<impl New>` when possible, instead.
///
/// # Safety
///
/// [`TryNew::try_new()`] must leave its destination argument in a valid,
/// initialized state when it returns `Ok`.
#[must_use = "`New`s do nothing until emplaced into storage"]
pub unsafe trait TryNew: Sized {
/// The type to construct.
type Output;
/// The error the construction operation may return.
type Error;
/// Try to construct a new value using the arguments stored in `self`.
///
/// # Safety
///
/// `this` must be freshly-created memory; this function must not
/// be used to mutate a previously-pinned pointer that has had `self: Pin`
/// functions called on it.
unsafe fn try_new(
self,
this: Pin<&mut MaybeUninit<Self::Output>>,
) -> Result<(), Self::Error>;
/// Adds a post-construction operation.
///
/// This function is analogous to [`New::with()`]; see its documentation for
/// more information.
///
/// Note: The return value of this function should not be relied upon; a
/// future version will replace it with `impl TryNew`.
fn with<F>(self, post: F) -> TryWith<Self, F> {
TryWith(self, post)
}
}
unsafe impl<N: New> TryNew for N {
type Output = N::Output;
type Error = Infallible;
unsafe fn try_new(
self,
this: Pin<&mut MaybeUninit<Self::Output>>,
) -> Result<(), Self::Error> {
self.new(this);
Ok(())
}
}
/// A pointer type that may be "emplaced" as a stable address which a [`New`] may be used to
/// construct a value with.
///
/// The `Emplace<T>::Output` type is usually either `Self` or `Pin<Self>` depending on the API of
/// `Self` with respect to [`DerefMut`].
///
/// For example, `Arc<T>`, `Box<T>`, and `Rc<T>` are all `Emplace<T, Output = Pin<Self>>`.
///
/// However, `cxx::UniquePtr<T>: Emplace<T, Output = Self>`, since `cxx::UniquePtr<T>` already only
/// allows obtaining pinned mutable references to `T` due to its more restrictive API, and hence
/// `cxx::UniquePtr<T>` does not need to be pinned itself.
pub trait Emplace<T>: Sized + Deref {
/// The stable address type within which a value of type `T` is emplaced.
type Output: Deref<Target = Self::Target>;
/// Constructs a new smart pointer and emplaces `n` into its storage.
fn emplace<N: New<Output = T>>(n: N) -> Self::Output {
match Self::try_emplace(n) {
Ok(x) => x,
Err(e) => match e {},
}
}
/// Constructs a new smart pointer and tries to emplace `n` into its storage.
fn try_emplace<N: TryNew<Output = T>>(n: N)
-> Result<Self::Output, N::Error>;
}
impl<T> Emplace<T> for Box<T> {
type Output = Pin<Self>;
fn try_emplace<N: TryNew<Output = T>>(
n: N,
) -> Result<Self::Output, N::Error> {
let mut uninit = Box::new(MaybeUninit::<T>::uninit());
unsafe {
let pinned = Pin::new_unchecked(&mut *uninit);
n.try_new(pinned)?;
Ok(Pin::new_unchecked(Box::from_raw(
Box::into_raw(uninit).cast::<T>(),
)))
}
}
}
impl<T> Emplace<T> for Rc<T> {
type Output = Pin<Self>;
fn try_emplace<N: TryNew<Output = T>>(
n: N,
) -> Result<Self::Output, N::Error> {
let uninit = Rc::new(MaybeUninit::<T>::uninit());
unsafe {
let pinned = Pin::new_unchecked(&mut *(Rc::as_ptr(&uninit) as *mut _));
n.try_new(pinned)?;
Ok(Pin::new_unchecked(Rc::from_raw(
Rc::into_raw(uninit).cast::<T>(),
)))
}
}
}
impl<T> Emplace<T> for Arc<T> {
type Output = Pin<Self>;
fn try_emplace<N: TryNew<Output = T>>(
n: N,
) -> Result<Self::Output, N::Error> {
let uninit = Arc::new(MaybeUninit::<T>::uninit());
unsafe {
let pinned = Pin::new_unchecked(&mut *(Arc::as_ptr(&uninit) as *mut _));
n.try_new(pinned)?;
Ok(Pin::new_unchecked(Arc::from_raw(
Arc::into_raw(uninit).cast::<T>(),
)))
}
}
}
#[doc(hidden)]
pub struct With<N, F>(N, F);
unsafe impl<N: New, F> New for With<N, F>
where
F: FnOnce(Pin<&mut N::Output>),
{
type Output = N::Output;
#[inline]
unsafe fn new(self, mut this: Pin<&mut MaybeUninit<Self::Output>>) {
self.0.new(this.as_mut());
// Now that `new()` has returned, we can assume `this` is initialized.
let this = this.map_unchecked_mut(|x| x.assume_init_mut());
(self.1)(this)
}
}
#[doc(hidden)]
pub struct TryWith<N, F>(N, F);
unsafe impl<N: TryNew, F> TryNew for TryWith<N, F>
where
F: FnOnce(Pin<&mut N::Output>) -> Result<(), N::Error>,
{
type Output = N::Output;
type Error = N::Error;
#[inline]
unsafe fn try_new(
self,
mut this: Pin<&mut MaybeUninit<Self::Output>>,
) -> Result<(), Self::Error> {
self.0.try_new(this.as_mut())?;
// Now that `new()` has returned, we can assume `this` is initialized.
let this = this.map_unchecked_mut(|x| x.assume_init_mut());
(self.1)(this)
}
}
/// A swappable type, which is able to efficiently swap the contents of two of
/// its values.
///
/// Unlike [`New`], `Swap` is safe, because it does not impose any requirements
/// on the swapped pointers.
///
/// It is possible to implement swapping with a source type that isn't `Self`.
pub trait Swap<Rhs = Self> {
/// Swaps the contents of `self` and `src` without running any destructors.
fn swap_with(self: Pin<&mut Self>, src: Pin<&mut Rhs>);
}