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 use core::convert::TryFrom;
16 use core::convert::TryInto;
17 use core::marker::PhantomData;
18 use core::mem::MaybeUninit;
19 use core::pin::Pin;
20 
21 use crate::new::New;
22 use crate::new::TryNew;
23 
24 /// Returns a [`New`] that uses the provided closure for construction.
25 ///
26 /// This is the most primitive [`New`]-creation function, and is almost-always
27 /// preferred over implementing [`New`] directly.
28 ///
29 /// # Safety
30 ///
31 /// `f` must respect the safety requirements of [`New`], since it is used
32 /// as an implementation basis.
33 #[inline]
by_raw<T, F>(f: F) -> impl New<Output = T> where F: FnOnce(Pin<&mut MaybeUninit<T>>),34 pub unsafe fn by_raw<T, F>(f: F) -> impl New<Output = T>
35 where
36   F: FnOnce(Pin<&mut MaybeUninit<T>>),
37 {
38   struct FnNew<F, T> {
39     f: F,
40     _ph: PhantomData<fn(T)>,
41   }
42 
43   unsafe impl<F, T> New for FnNew<F, T>
44   where
45     F: FnOnce(Pin<&mut MaybeUninit<T>>),
46   {
47     type Output = T;
48     #[inline]
49     unsafe fn new(self, this: Pin<&mut MaybeUninit<Self::Output>>) {
50       (self.f)(this)
51     }
52   }
53 
54   FnNew::<F, T> {
55     f,
56     _ph: PhantomData,
57   }
58 }
59 
60 /// Returns a [`New`] that uses the provided closure for constructing a
61 /// `T`.
62 ///
63 /// ```
64 /// # use moveit::{moveit, new};
65 /// moveit! {
66 ///   let x = new::by(|| 21 * 2);
67 /// }
68 /// assert_eq!(*x, 42);
69 /// ```
70 #[inline]
by<T, F>(f: F) -> impl New<Output = T> where F: FnOnce() -> T,71 pub fn by<T, F>(f: F) -> impl New<Output = T>
72 where
73   F: FnOnce() -> T,
74 {
75   unsafe { by_raw(|mut this| this.set(MaybeUninit::new(f()))) }
76 }
77 
78 /// Returns a [`New`] that uses a [`From`] implementation to generate a `T`.
79 ///
80 /// ```
81 /// # use std::pin::Pin;
82 /// # use moveit::{moveit, new, MoveRef};
83 /// moveit! {
84 ///   let x: Pin<MoveRef<String>> = new::from("foo");
85 /// }
86 /// assert_eq!(*x, "foo");
87 /// ```
88 #[inline]
from<T: From<U>, U>(val: U) -> impl New<Output = T>89 pub fn from<T: From<U>, U>(val: U) -> impl New<Output = T> {
90   by(|| val.into())
91 }
92 
93 /// Returns a [`New`] that simply returns the given value.
94 ///
95 /// ```
96 /// # use std::pin::Pin;
97 /// # use moveit::{moveit, new};
98 /// moveit! {
99 ///   let x = new::of(42);
100 /// }
101 /// assert_eq!(*x, 42);
102 /// ```
103 ///
104 /// In general, you will almost always want [`from()`].
105 #[inline]
of<T>(val: T) -> impl New<Output = T>106 pub fn of<T>(val: T) -> impl New<Output = T> {
107   by(|| val)
108 }
109 
110 /// Returns a [`New`] calls [`Default`] to generate a `T`.
111 ///
112 /// ```
113 /// # use std::pin::Pin;
114 /// # use moveit::{moveit, new};
115 /// moveit! {
116 ///   let x = new::default::<i32>();
117 /// }
118 /// assert_eq!(*x, 0);
119 /// ```
120 #[inline]
default<T: Default>() -> impl New<Output = T>121 pub fn default<T: Default>() -> impl New<Output = T> {
122   by(Default::default)
123 }
124 
125 /// Returns a [`TryNew`] that uses the provided closure for construction.
126 ///
127 /// This is the most primitive [`TryNew`]-creation function, and is
128 /// almost-always preferred over implementing [`TryNew`] directly.
129 ///
130 /// # Safety
131 ///
132 /// `f` must respect the safety requirements of [`TryNew`], since it is used
133 /// as an implementation basis.
134 #[inline]
try_by_raw<T, E, F>(f: F) -> impl TryNew<Output = T, Error = E> where F: FnOnce(Pin<&mut MaybeUninit<T>>) -> Result<(), E>,135 pub unsafe fn try_by_raw<T, E, F>(f: F) -> impl TryNew<Output = T, Error = E>
136 where
137   F: FnOnce(Pin<&mut MaybeUninit<T>>) -> Result<(), E>,
138 {
139   struct FnNew<F, T, E> {
140     f: F,
141     _ph: PhantomData<fn(T) -> E>,
142   }
143 
144   unsafe impl<F, T, E> TryNew for FnNew<F, T, E>
145   where
146     F: FnOnce(Pin<&mut MaybeUninit<T>>) -> Result<(), E>,
147   {
148     type Output = T;
149     type Error = E;
150     #[inline]
151     unsafe fn try_new(
152       self,
153       this: Pin<&mut MaybeUninit<Self::Output>>,
154     ) -> Result<(), E> {
155       (self.f)(this)
156     }
157   }
158 
159   FnNew::<F, T, E> {
160     f,
161     _ph: PhantomData,
162   }
163 }
164 
165 /// Returns a [`TryNew`] that uses the provided closure for constructing a
166 /// `T`.
167 #[inline]
try_by<T, E, F>(f: F) -> impl TryNew<Output = T, Error = E> where F: FnOnce() -> Result<T, E>,168 pub fn try_by<T, E, F>(f: F) -> impl TryNew<Output = T, Error = E>
169 where
170   F: FnOnce() -> Result<T, E>,
171 {
172   unsafe {
173     try_by_raw(|this| {
174       this.get_unchecked_mut().write(f()?);
175       Ok(())
176     })
177   }
178 }
179 
180 /// Returns a [`TryNew`] that uses a `TryFrom` implementation to generate a `T`.
181 #[inline]
try_from<T: TryFrom<U>, U>( val: U, ) -> impl TryNew<Output = T, Error = T::Error>182 pub fn try_from<T: TryFrom<U>, U>(
183   val: U,
184 ) -> impl TryNew<Output = T, Error = T::Error> {
185   try_by(|| val.try_into())
186 }
187