frui_macros 0.0.1

Macros for Frui UI framework
Documentation
use proc_macro::TokenStream;
use quote::{format_ident, quote};
use syn::{parse::Parse, Expr, ExprRange};

pub fn impl_tuple_slice(tokens: TokenStream) -> TokenStream {
    let input = syn::parse_macro_input!(tokens as Range);

    let o = (input.start..input.end).map(|args_count| {
        let bounds_1 = (0..args_count).map(|i| format_ident!("_{i}"));
        let bounds_2 = (0..args_count).map(|i| format_ident!("_{i}"));
        let bounds_3 = (0..args_count).map(syn::Index::from);

        quote! {
            impl< #(#bounds_1 : Widget),* > WidgetList for ( #(#bounds_2,)* ) {
                fn get(&self) -> Vec<&dyn Widget> {
                    vec![ #( &self.#bounds_3 ),* ]
                }
            }
        }
    });

    (quote! { #(#o)* }).into()
}

#[derive(Debug)]
struct Range {
    start: usize,
    end: usize,
}

impl Parse for Range {
    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
        let range = input.parse::<ExprRange>()?;
        Ok(Self {
            start: extract_usize(&range.from),
            end: extract_usize(&range.to),
        })
    }
}

fn extract_usize(range: &Option<Box<Expr>>) -> usize {
    match range.as_ref().unwrap().as_ref() {
        Expr::Lit(lit) => match &lit.lit {
            syn::Lit::Int(v) => v.base10_parse().unwrap(),
            _ => panic!(),
        },
        _ => panic!(),
    }
}