""" This is a helper script to generate the multi-field variants of the __c_enum_impl! macro. USAGE: python3 scripts/enum-impl.py > src/decl_variants.rs """ def emit_multi_variant(count): print( f"""\ // Match {count} fields ( impl($name:ident, $inner:ty, $default:expr) """ ) for i in range(0, count): index = i + 1 print( f"""\ $( #[$attr{index}:meta] )* $field{index}:ident $( = $value{index}:expr )? , """ ) print( """\ $( $( #[$rattr:meta] )* $frest:ident $( = $frest_val:expr )? ),* $(,)? ) => {\ """ ) for i in range(0, count): index = i + 1 if index == 1: prev = "$default" else: prev = f"Self::$field{index - 1}.0 + 1" print( f"""\ $( #[$attr{index}] )* #[allow(non_upper_case_globals)] pub const $field{index}: Self = Self($crate::__c_enum_impl!( impl(first_expr) $( $value{index}, )? {prev})); """ ) print( f"""\ $crate::__c_enum_decl_variants!( impl($name, $inner, Self::$field{count}.0 + 1) $( $( #[$rattr] )* $frest $( = $frest_val )?, )* ); }}; """ ) print( """\ /// Helper macro for defining the fields of a c_enum! /// /// Large enums can easily hit the recursion limit imposed by rustc on macros. /// This macro defines a bunch of variants which consume a bunch of fields at /// once with the goal being to reduce the recursion limit to something /// managable even for large enum definitions. /// /// This code is generated by scripts/enum-impl.py. Don't edit it manually. /// Edit the script and regenerate it instead. #[doc(hidden)] #[macro_export] macro_rules! __c_enum_decl_variants { (impl($name:ident, $inner:ty, $default:expr)) => {}; """ ) # ~10k variants ought to be enough for now. Anyone going over that can probably # afford to bump up rustc's recursion limit. emit_multi_variant(128) emit_multi_variant(32) emit_multi_variant(8) print( """\ // Base case ( impl($name:ident, $inner:ty, $default:expr) $( #[$fattr:meta] )* $field:ident $( = $fvalue:expr )? $( , $( #[$rattr:meta] )* $frest:ident $( = $frest_val:expr )? )* $(,)? ) => { $( #[$fattr] )* #[allow(non_upper_case_globals)] pub const $field: Self = Self($crate::__c_enum_impl!( impl(first_expr) $( $fvalue, )? $default)); $crate::__c_enum_decl_variants!( impl($name, $inner, Self::$field.0 + 1) $( $( #[$rattr] )* $frest $( = $frest_val )?, )* ); } }\ """ )