// 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. use core::convert::TryFrom; use core::convert::TryInto; use core::marker::PhantomData; use core::mem::MaybeUninit; use core::pin::Pin; use crate::new::New; use crate::new::TryNew; /// Returns a [`New`] that uses the provided closure for construction. /// /// This is the most primitive [`New`]-creation function, and is almost-always /// preferred over implementing [`New`] directly. /// /// # Safety /// /// `f` must respect the safety requirements of [`New`], since it is used /// as an implementation basis. #[inline] pub unsafe fn by_raw(f: F) -> impl New where F: FnOnce(Pin<&mut MaybeUninit>), { struct FnNew { f: F, _ph: PhantomData, } unsafe impl New for FnNew where F: FnOnce(Pin<&mut MaybeUninit>), { type Output = T; #[inline] unsafe fn new(self, this: Pin<&mut MaybeUninit>) { (self.f)(this) } } FnNew:: { f, _ph: PhantomData, } } /// Returns a [`New`] that uses the provided closure for constructing a /// `T`. /// /// ``` /// # use moveit::{moveit, new}; /// moveit! { /// let x = new::by(|| 21 * 2); /// } /// assert_eq!(*x, 42); /// ``` #[inline] pub fn by(f: F) -> impl New where F: FnOnce() -> T, { unsafe { by_raw(|mut this| this.set(MaybeUninit::new(f()))) } } /// Returns a [`New`] that uses a [`From`] implementation to generate a `T`. /// /// ``` /// # use std::pin::Pin; /// # use moveit::{moveit, new, MoveRef}; /// moveit! { /// let x: Pin> = new::from("foo"); /// } /// assert_eq!(*x, "foo"); /// ``` #[inline] pub fn from, U>(val: U) -> impl New { by(|| val.into()) } /// Returns a [`New`] that simply returns the given value. /// /// ``` /// # use std::pin::Pin; /// # use moveit::{moveit, new}; /// moveit! { /// let x = new::of(42); /// } /// assert_eq!(*x, 42); /// ``` /// /// In general, you will almost always want [`from()`]. #[inline] pub fn of(val: T) -> impl New { by(|| val) } /// Returns a [`New`] calls [`Default`] to generate a `T`. /// /// ``` /// # use std::pin::Pin; /// # use moveit::{moveit, new}; /// moveit! { /// let x = new::default::(); /// } /// assert_eq!(*x, 0); /// ``` #[inline] pub fn default() -> impl New { by(Default::default) } /// Returns a [`TryNew`] that uses the provided closure for construction. /// /// This is the most primitive [`TryNew`]-creation function, and is /// almost-always preferred over implementing [`TryNew`] directly. /// /// # Safety /// /// `f` must respect the safety requirements of [`TryNew`], since it is used /// as an implementation basis. #[inline] pub unsafe fn try_by_raw(f: F) -> impl TryNew where F: FnOnce(Pin<&mut MaybeUninit>) -> Result<(), E>, { struct FnNew { f: F, _ph: PhantomData E>, } unsafe impl TryNew for FnNew where F: FnOnce(Pin<&mut MaybeUninit>) -> Result<(), E>, { type Output = T; type Error = E; #[inline] unsafe fn try_new( self, this: Pin<&mut MaybeUninit>, ) -> Result<(), E> { (self.f)(this) } } FnNew:: { f, _ph: PhantomData, } } /// Returns a [`TryNew`] that uses the provided closure for constructing a /// `T`. #[inline] pub fn try_by(f: F) -> impl TryNew where F: FnOnce() -> Result, { unsafe { try_by_raw(|this| { this.get_unchecked_mut().write(f()?); Ok(()) }) } } /// Returns a [`TryNew`] that uses a `TryFrom` implementation to generate a `T`. #[inline] pub fn try_from, U>( val: U, ) -> impl TryNew { try_by(|| val.try_into()) }