use proc_macro2::{Span, TokenStream};
use quote::quote;
use syn::{Expr, GenericParam, Generics, Ident, TypeParamBound, parse_quote};
use crate::parser::EnumInfo;
pub fn add_trait_bounds(generics: &mut Generics, bound: &TypeParamBound) {
for param in &mut generics.params {
if let GenericParam::Type(ref mut type_param) = *param {
type_param.bounds.push(bound.clone());
}
}
}
pub struct DiscriminantInfo {
pub discriminant_consts: Vec<TokenStream>,
pub discriminant_names: Vec<Ident>,
pub variant_names: Vec<Ident>,
pub discriminant_type: Ident,
}
pub fn variant_discriminants(enum_info: &EnumInfo) -> DiscriminantInfo {
let mut discriminant_consts = Vec::new();
let mut discriminant_names = Vec::new();
let mut variant_names = Vec::new();
let discriminant_type = enum_info
.discriminant_type
.clone()
.unwrap_or(Ident::new("isize", Span::mixed_site()));
let mut previous_discriminant = None;
for (i, variant) in enum_info.variants.iter().enumerate() {
variant_names.push(variant.name.clone());
let discriminant = if let Some(expr) = &variant.discriminant {
expr.clone()
} else if let Some(expr) = previous_discriminant {
let expr: Expr = parse_quote!( #expr + 1 );
expr
} else {
let expr: Expr = parse_quote!(0);
expr
};
previous_discriminant = Some(discriminant.clone());
let discriminant_name = Ident::new(&format!("DISCRIMINANT_{i}"), Span::mixed_site());
discriminant_names.push(discriminant_name.clone());
discriminant_consts.push(quote! {
const #discriminant_name: #discriminant_type = #discriminant;
});
}
DiscriminantInfo {
discriminant_consts,
discriminant_names,
variant_names,
discriminant_type,
}
}