Skip to content

Instantly share code, notes, and snippets.

@novafacing
Last active July 9, 2024 06:43
Show Gist options
  • Save novafacing/6974cd0bf1c77285f72251c931ae9afc to your computer and use it in GitHub Desktop.
Save novafacing/6974cd0bf1c77285f72251c931ae9afc to your computer and use it in GitHub Desktop.
Declarative macro to parse an enum item completely including generic parameters, where clauses and bounds, and attributes.
macro_rules! parse_enum_variant {
{
$(#[$enum_meta:meta])*,
$vis:vis,
$name:ident,
$(<$($generic_param:tt),*>)?,
@where_clauses {$($where:tt)*},
@parse {$($eout:tt)*},
#[$variant_meta:meta]
$($rest:tt)*
} => {
parse_enum_variant! {
$(#[$enum_meta])*,
$vis,
$name,
$(<$($generic_param),*>)?,
@where_clauses {$($where)*},
@parse {
$($eout)*
#[$variant_meta]
},
$($rest)*
}
};
{
$(#[$enum_meta:meta])*,
$vis:vis,
$name:ident,
$(<$($generic_param:tt),*>)?,
@where_clauses {$($where:tt)*},
@parse {$($eout:tt)*},
$variant:ident,
$($rest:tt)*
} => {
parse_enum_variant! {
$(#[$enum_meta])*,
$vis,
$name,
$(<$($generic_param),*>)?,
@where_clauses {$($where)*},
@parse {
$($eout)*
$variant,
},
$($rest)*
}
};
{
$(#[$enum_meta:meta])*,
$vis:vis,
$name:ident,
$(<$($generic_param:tt),*>)?,
@where_clauses {$($where:tt)*},
@parse {$($eout:tt)*},
$variant:ident = $value:expr,
$($rest:tt)*
} => {
parse_enum_variant!{
$(#[$enum_meta])*,
$vis,
$name,
$(<$($generic_param),*>)?,
@where_clauses {$($where)*},
@parse {
$($eout)*
$variant = $value,
},
$($rest)*
}
};
{
$(#[$enum_meta:meta])*,
$vis:vis,
$name:ident,
$(<$($generic_param:tt),*>)?,
@where_clauses {$($where:tt)*},
@parse {$($eout:tt)*},
$variant:ident($param:ty),
$($rest:tt)*
} => {
parse_enum_variant!{
$(#[$enum_meta])*,
$vis,
$name,
$(<$($generic_param),*>)?,
@where_clauses {$($where)*},
@parse {
$($eout)*
$variant($param),
},
$($rest)*
}
};
{
$(#[$enum_meta:meta])*,
$vis:vis,
$name:ident,
$(<$($generic_param:tt),*>)?,
@where_clauses {$($where:tt)*},
@parse {$($eout:tt)*},
$variant:ident { $($fields:tt)* },
$($rest:tt)*
} => {
parse_enum_variant!{
$(#[$enum_meta])*,
$vis,
$name,
$(<$($generic_param),*>)?,
@where_clauses {$($where)*},
@parse {
$($eout)*
$variant { $($fields)* },
},
$($rest)*
}
};
{
$(#[$enum_meta:meta])*,
$vis:vis,
$name:ident,
$(<$($generic_param:tt),*>)?,
@where_clauses {$($where:tt)*},
@parse {$($eout:tt)*} $(,)*
} => {
$(#[$enum_meta])*
$vis enum $name
$(<$($generic_param),*>)?
$($where)*
{
$($eout)*
}
};
{
$(#[$enum_meta:meta])*,
$vis:vis,
$name:ident,
$(<$($generic_param:tt),*>)?,
@where_clauses {$($where:tt)*},
@parse {$($eout:tt)*} $(,)*
} => {
$(#[$enum_meta])*
$vis enum $name
$(<$($generic_param),*>)?
$($where)*
{
$($eout)*
}
};
{
$(#[$enum_meta:meta])*,
$vis:vis,
$name:ident,
$(<$($generic_param:tt),*>)?,
@where_clauses {$($where:tt)*},
@parse {$($eout:tt)*} $(,)*
} => {
$(#[$enum_meta])*
$vis enum $name
$(<$($generic_param),*>)?
$($where)*
{
$($eout)*
}
};
{
$(#[$enum_meta:meta])*,
$vis:vis,
$name:ident,
$(<$($generic_param:tt),*>)?,
@where_clauses {$($where:tt)*},
@parse {$($eout:tt)*} $(,)*
} => {
$(#[$enum_meta])*
$vis enum $name
$(<$($generic_param),*>)?
$($where)*
{
$($eout)*
}
};
}
macro_rules! parse_enum {
(
$(#[$enum_meta:meta])*
$vis:vis enum $enum_name:ident
$(<$($generic_param:tt),*>)?
{
$($variants:tt)*
}
) => {
parse_enum_variant! {
$(#[$enum_meta])*,
$vis,
$enum_name,
$(<$($generic_param),*>)?,
@where_clauses {},
@parse {}, $($variants)*
}
};
(
$(#[$enum_meta:meta])*
$vis:vis enum $enum_name:ident
$(<$($generic_param:tt),*>)?
where
$where_clause:tt $(<$($where_generic_param:tt),*>)?:
$where_clause_bound:tt $(<$($where_clause_bound_generic_param:tt),*>)?
$(+ $where_clause_bound_plus:tt $(<$($where_clause_bound_generic_param_plus:tt),*>)?)*
$(, $more_where_clause:tt $(<$($more_where_generic_param:tt),*>)?:
$more_where_clause_bound:tt $(<$($more_where_clause_bound_generic_param:tt),*>)?
$(+ $more_where_clause_bound_plus:tt $(<$($more_where_clause_bounds_generic_param_plus:tt),*>)?)* )*
{
$($variants:tt)*
}
) => {
parse_enum_variant! {
$(#[$enum_meta])*,
$vis,
$enum_name,
$(<$($generic_param),*>)?,
@where_clauses {
where
$where_clause $(<$($where_generic_param),*>)?:
$where_clause_bound $(<$($where_clause_bound_generic_param),*>)?
$(+ $where_clause_bound_plus $(<$($where_clause_bound_generic_param_plus),*>)?)*
$(, $more_where_clause $(<$($more_where_generic_param),*>)?:
$more_where_clause_bound $(<$($more_where_clause_bound_generic_param),*>)?
$(+ $more_where_clause_bound_plus $(<$($more_where_clause_bounds_generic_param_plus),*>)?)* )*
},
@parse {}, $($variants)*
}
};
}
@novafacing
Copy link
Author

novafacing commented Jul 8, 2024

Inline generic bounds enum X<T: Foo> { Y } are left as an exercise for the reader, I only use where clauses ;) same with impl Trait because I just don't care about it.

@novafacing
Copy link
Author

FAQ:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment