instance_code 0.1.4

Turn instances into source code
Documentation
use std::marker::PhantomData;

use super::*;

macro_rules! primitive {
    ($($type:ty),*) => {
        $(
            impl InstanceCode for $type {
                fn instance_code(&self) -> TokenStream {
                    quote! {
                        #self
                    }
                }
            }
        )*
    }
}

primitive!(
    u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, f32, f64, &str, char, bool
);

impl<'a, T: ?Sized> InstanceCode for &'a T
where
    T: InstanceCode,
{
    fn instance_code(&self) -> TokenStream {
        let t = <T as InstanceCode>::instance_code(*self);
        quote! {
            &#t
        }
    }
}

impl<T> InstanceCode for [T]
where
    T: InstanceCode,
{
    fn instance_code(&self) -> TokenStream {
        let slice = self.iter().map(|d| d.instance_code());
        quote!([#(#slice),*])
    }
}

impl<T, const N: usize> InstanceCode for [T; N]
where
    T: InstanceCode,
{
    fn instance_code(&self) -> TokenStream {
        self.as_slice().instance_code()
    }
}

impl<T> InstanceCode for Option<T>
where
    T: InstanceCode,
{
    fn instance_code(&self) -> TokenStream {
        match self {
            None => quote! { None },
            Some(t) => {
                let t = t.instance_code();
                quote! { Some(#t) }
            }
        }
    }
}

impl<T, E> InstanceCode for Result<T, E>
where
    T: InstanceCode,
    E: InstanceCode,
{
    fn instance_code(&self) -> TokenStream {
        match self {
            Ok(ok) => {
                let ok = ok.instance_code();
                quote!(Ok(#ok))
            }
            Err(e) => {
                let e = e.instance_code();
                quote!(Err(#e))
            }
        }
    }
}

impl<T> InstanceCode for PhantomData<T> {
    fn instance_code(&self) -> TokenStream {
        quote! {
            ::core::marker::PhantomData
        }
    }
}

macro_rules! tuple {
    ($($ty:ident),*) => {
        #[allow(non_snake_case)]
        impl<$($ty),*> InstanceCode for ($($ty,)*) where $($ty: InstanceCode),* {
            fn instance_code(&self) -> TokenStream {
                let ($($ty,)*) = self;
                $(
                    let $ty = $ty.instance_code();
                )*
                quote! {
                    ($(#$ty),*)
                }
            }
        }
    }
}

tuple!();
tuple!(A);
tuple!(A, B);
tuple!(A, B, C);
tuple!(A, B, C, D);
tuple!(A, B, C, D, E);
tuple!(A, B, C, D, E, F);
tuple!(A, B, C, D, E, F, G);
tuple!(A, B, C, D, E, F, G, H);
tuple!(A, B, C, D, E, F, G, H, I);
tuple!(A, B, C, D, E, F, G, H, I, J);