diff --git a/src/lib.rs b/src/lib.rs index 06c6020..2768fad 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -187,6 +187,25 @@ fn concat(mut v1: Vec, mut v2: Vec) -> Vec { v1 } +fn check_for_default(triples: &mut Vec<(TokenStream, Ident, TokenTree)>) { + let mut default_position: Option = None; + for (attributes, _variant_name, variant_value) in triples.into_iter() { + if attributes.to_string().contains("default") { + if default_position.is_some() { + // error!("Multiple variants marked as default"); + } + default_position = Some(variant_value.to_string().parse::().unwrap()); + } + } + if !default_position.is_some() { + // No default specified, so we'll just use the first variant + triples[0].0.extend(vec![ + punct_token('#'), + bracket_token(vec![ident_token("default")]).into(), + ]); + } +} + #[proc_macro] pub fn primitive_enum(tokens: TokenStream) -> TokenStream { let mut iter = tokens.into_iter(); @@ -302,6 +321,7 @@ pub fn primitive_enum(tokens: TokenStream) -> TokenStream { offset += 1; triples.push((variant_attributes, variant_name, value)); } + check_for_default(&mut triples); // make sure there's a default, if the user didn't specify one triples }; @@ -322,7 +342,6 @@ pub fn primitive_enum(tokens: TokenStream) -> TokenStream { ident_token("repr"), paren_token(repr_type.clone()), ])); - // #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] out.push(punct_token('#')); out.push(bracket_token(vec![ @@ -339,8 +358,11 @@ pub fn primitive_enum(tokens: TokenStream) -> TokenStream { ident_token("Eq"), punct_token(','), ident_token("Hash"), + punct_token(','), + ident_token("Default"), ]), ])); + out.push(ident_token("pub")); out.push(ident_token("enum")); out.push(TokenTree::Ident(enum_identifier.clone())); diff --git a/tests/sample.rs b/tests/sample.rs index 2bc8766..1b4fe40 100644 --- a/tests/sample.rs +++ b/tests/sample.rs @@ -196,4 +196,22 @@ mod tests { assert_eq!(MarkerType::from_name("Markerboxes"), Some(MarkerType::Markerboxes)); assert_eq!(MarkerType::from_name("Markerpitlane"), Some(MarkerType::Markerpitlane)); } + + primitive_enum! { MarkerType2 u32 ; + A, // 0 + B, // 1 + C, // 2 + D, // 3 + E, // 4 + #[default] + F, // 5 + G, // 6 + } + + #[test] + fn test_enum_default() { + assert_eq!(MarkerType2::default(), MarkerType2::F); + assert_eq!(MarkerType2::from(0), Some(MarkerType2::A)); + assert_eq!(MyEnum::default(), MyEnum::A); + } }