1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
// @author: olinex
// @time: 2022/07/18
//! # Enum Group
//! `enum-group` is a simple derive macro crate that helps enum types to group their variants.
//! Annotate an enum with `#[derive(EnumGroup)]`,
//! and mark variants some group label names with `#[groups(label1, label2)]`
//! will auto generate function `is_label1` and `is_label2`.
//! These functions will tell you if a variant of the enum belongs to this grouping.
//!
//! ## Example
//! ```
//! use enum_group::EnumGroup;
//!
//! #[derive(EnumGroup)]
//! enum Number {
//! #[groups(odd)]
//! One,
//!
//! #[groups(even, prime)]
//! Two,
//!
//! #[groups(odd, prime)]
//! Three,
//!
//! Unknown(usize)
//! }
//!
//! // will auto generate function `fn is_odd(&self) -> bool`
//! assert!(Number::One.is_odd());
//! assert!(!Number::Two.is_odd());
//! assert!(Number::Three.is_odd());
//! assert!(!Number::Unknown(0).is_odd());
//!
//! // will auto generate function `fn is_even(&self) -> bool`
//! assert!(!Number::One.is_even());
//! assert!(Number::Two.is_even());
//! assert!(!Number::Three.is_even());
//! assert!(!Number::Unknown(0).is_even());
//!
//! // will auto generate function `fn is_prime(&self) -> bool`
//! assert!(!Number::One.is_prime());
//! assert!(Number::Two.is_prime());
//! assert!(Number::Three.is_prime());
//! assert!(!Number::Unknown(0).is_prime());
//! ```
//!
//! ## Usage Restrictions
//! Each character of the group label name for each variant must be alphanumeric or `_`.
//!
//! ## Panic
//! ```
//! use enum_group::EnumGroup;
//!
//! #[derive(EnumGroup)]
//! enum Number {
//! // #[groups(odd_&)] groups attribute ident can only contain the characters a-zA-Z0-9_
//! // #[groups(_odd)] groups attribute ident must starts wtih characters a-zA-Z
//! // #[groups(odd_)] groups attribute ident must ends wtih characters a-zA-Z
//! // #[groups()] must have group ident in groups attribute
//! One,
//! }
//! ```
extern crate proc_macro;
// self mods
mod context;
// use other mods
use proc_macro::TokenStream;
use syn::{parse_macro_input, DeriveInput};
// use self mods
use context::EnumGroupContext;
#[proc_macro_derive(EnumGroup, attributes(groups))]
pub fn derive_enum_group(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let ctx = match EnumGroupContext::new(&input) {
Ok(ctx) => ctx,
Err(e) => return e.to_compile_error().into(),
};
match ctx.generate() {
Ok(stream) => stream.into(),
Err(e) => e.to_compile_error().into(),
}
}