instrs-derive 0.1.0

Derive macro for instrs crate
Documentation
use proc_macro2::{TokenStream, Literal};
use proc_macro::TokenStream as TStream;
use quote_into::quote_into;
use syn::{*, spanned::Spanned};

pub(crate) struct Instruction {
    pub name: Ident,
    pub fields: Fields,
}

impl From<Variant> for Instruction {
    fn from(value: Variant) -> Self {
        Self { name: value.ident, fields: value.fields }
    }
}

pub(crate) struct Info {
    pub name: Ident,
    pub generics: Generics,
    pub instructions: Vec<Instruction>,
    pub repr: Box<dyn Fn(usize) -> Literal>,
}

impl From<DeriveInput> for Info {
    fn from(value: DeriveInput) -> Self {
        let name = value.ident;
        let generics = value.generics;

        let Data::Enum(data) = value.data else {panic!("derive macro currently only supports enums")};

        let instructions: Vec<_> = data.variants.into_iter()
            .map(|variant| variant.into())
            .collect(); 

        let last_variant = match instructions.len().checked_sub(1) {
            Some(n) => n,
            None => 0,
        };

        let repr = Box::new(match last_variant.checked_ilog2() {
            Some(n) => match n {
                00..=07 => |n: usize| Literal::u8_suffixed(n.try_into().unwrap()),
                08..=15 => |n: usize| Literal::u16_suffixed(n.try_into().unwrap()),
                16..=31 => |n: usize| Literal::u32_suffixed(n.try_into().unwrap()),
                32..=63 => |n: usize| Literal::u64_suffixed(n.try_into().unwrap()),
                64..=127 => |n: usize| Literal::u128_suffixed(n.try_into().unwrap()),
                _ => panic!("Enums with >=2^128 variants are not supported\nAlso how did you even do that lmao"),
            },
            None => |n: usize| Literal::u8_suffixed(n.try_into().unwrap()),
        });

        Self { name, generics, instructions, repr, }
    }
}