use crate::{
exports::Struct,
runtime::{
Cell,
Downcast,
Ident,
Origin,
Provider,
RuntimeError,
RuntimeResult,
ScriptType,
TypeHint,
Upcast,
},
};
macro_rules! impl_tuple {
($($arg:ident: $index:tt),+) => {
impl<'a $(, $arg)+> Downcast<'a> for ($($arg, )+)
where
$(
$arg: Downcast<'static>,
)+
{
fn downcast(origin: Origin, provider: Provider<'a>) -> RuntimeResult<Self> {
let structure_origin = provider.as_ref().origin();
let structure = provider
.to_borrowed(&origin)?
.borrow_ref::<Struct>(origin)?;
Ok((
$(
match structure.map.get(&Ident::from_string(stringify!($index))) {
Some(entry) => <$arg as Downcast>::downcast(
origin,
Provider::Owned(entry.clone()),
)?,
None => {
return Err(RuntimeError::UnknownField {
access_origin: origin,
receiver_origin: structure_origin,
receiver_type: Struct::type_meta(),
field: String::from(stringify!($index)),
})
}
},
)+
))
}
#[inline(always)]
fn hint() ->TypeHint {
TypeHint::Type(Struct::type_meta())
}
}
impl<'a $(, $arg)+> Upcast<'a> for ($($arg, )+)
where
$(
$arg: Upcast<'static>,
)+
{
type Output = Box<Struct>;
fn upcast(origin: Origin, this: Self) -> RuntimeResult<Self::Output> {
Ok(Box::new(Struct {
map: [
$((
Ident::from_string(stringify!($index)),
Cell::give(origin, this.$index)?,
),)+
].into()
}))
}
#[inline(always)]
fn hint() -> TypeHint {
TypeHint::Type(Struct::type_meta())
}
}
};
}
impl_tuple!(A: 0);
impl_tuple!(A: 0, B: 1);
impl_tuple!(A: 0, B: 1, C: 2);
impl_tuple!(A: 0, B: 1, C: 2, D: 3);
impl_tuple!(A: 0, B: 1, C: 2, D: 3, E: 4);
impl_tuple!(A: 0, B: 1, C: 2, D: 3, E: 4, F: 5);
impl_tuple!(A: 0, B: 1, C: 2, D: 3, E: 4, F: 5, G: 6);