// Copyright (C) 2025 Emilis Bliūdžius // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . use quote::{ToTokens, quote}; use syn::spanned::Spanned; pub struct All { name: syn::Ident, variants: Box<[syn::Ident]>, } impl All { pub fn parse(input: syn::DeriveInput) -> Result { let data = match input.data { syn::Data::Enum(enu) => enu, _ => { return Err(syn::Error::new( input.span(), "All can only be used on enums", )); } }; let variants = data .variants .into_iter() .map(|v| match &v.fields { syn::Fields::Named(_) | syn::Fields::Unnamed(_) => Err(syn::Error::new( v.ident.span(), "All can only be used on enums with only unit fields", )), syn::Fields::Unit => Ok(v.ident), }) .collect::, _>>()?; let name = input.ident; Ok(Self { name, variants }) } } impl ToTokens for All { fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { let name = &self.name; let variants = &self.variants; let count = self.variants.len(); tokens.extend(quote! { impl #name { pub const ALL: [#name; #count] = [#(#name::#variants),*]; } }); } }