use super::{Capsule, CapsuleMut, Scope};
pub trait Encapsulate<'env> {
type Encapsulated;
fn encapsulate(self, scope: &Scope<'env>) -> Self::Encapsulated;
}
impl<'env, T: ?Sized + Sync> Encapsulate<'env> for &'env T {
type Encapsulated = Capsule<T>;
fn encapsulate(self, scope: &Scope<'env>) -> Self::Encapsulated {
scope.encapsulate(self)
}
}
impl<'env, T: ?Sized + Sync> Encapsulate<'env> for &'env mut T {
type Encapsulated = CapsuleMut<T>;
fn encapsulate(self, scope: &Scope<'env>) -> Self::Encapsulated {
scope.encapsulate_mut(self)
}
}
macro_rules! encapsulate_tuples {
($n:ident : $t:ident) => {
encapsulate_tuples!(@impl $n:$t);
};
($hn:ident : $ht:ident $($tn:ident : $tt:ident)+) => {
encapsulate_tuples!(@impl $($tn:$tt)+);
encapsulate_tuples!(@impl $hn:$ht $($tn:$tt)+);
};
(@impl $($n:ident:$T:ident)+) => {
impl<'env, $($T: Encapsulate<'env>,)*> Encapsulate<'env> for ($($T,)+) {
type Encapsulated = ($($T::Encapsulated,)+);
fn encapsulate(self, scope: &Scope<'env>) -> Self::Encapsulated {
let ($($n,)+) = self;
($($n.encapsulate(scope),)+)
}
}
};
}
encapsulate_tuples!(a:A b:B c:C d:D e:E f:F g:G h:H);
impl<'env, T: Encapsulate<'env>, const N: usize> Encapsulate<'env> for [T; N] {
type Encapsulated = [T::Encapsulated; N];
fn encapsulate(self, scope: &Scope<'env>) -> Self::Encapsulated {
self.map(|i| i.encapsulate(scope))
}
}
pub struct Gen<F>(pub F);
pub fn gen<'env, F, T>(f: F) -> Gen<F>
where
F: FnOnce(&Scope<'env>) -> T,
{
Gen(f)
}
impl<'env, F, T> Encapsulate<'env> for Gen<F>
where
F: FnOnce(&Scope<'env>) -> T,
{
type Encapsulated = T;
fn encapsulate(self, scope: &Scope<'env>) -> T {
self.0(scope)
}
}