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 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
#![doc = include_str!("../README.md")]
use proc_macro::TokenStream;
use proc_macro_error::proc_macro_error;
/// Macro that implements bunch of traits for enums that
/// simply are aliases for integer type
///
/// example:
/// ```
/// use integral_enum::IntegralEnum;
///
/// #[derive(IntegralEnum)]
/// #[repr(u8)]
/// // repr is not required, by default `IntegralEnum` assumes that repr is u8
/// // FIXME: repr should be infered to avoid specific errors
/// pub enum Yuu {
/// Hatred,
/// Pain,
/// }
///
/// assert_eq!(Yuu::try_from(0), Ok(Yuu::Hatred));
/// assert_eq!(Yuu::try_from(1), Ok(Yuu::Pain));
/// assert_eq!(Yuu::try_from(123), Err(()));
/// ```
///
/// Macro will automatically generate such trait
/// implementations: Clone, Copy, PartialEq, Eq, Debug,
/// Display, TryFrom.
///
/// To resolve conflicts with other derive-macro you should
/// use the #[enum_disable(...)] attribute, it has the
/// following options:
///
/// `debug`, `display`, `clone`, `copy`, `partial_eq`,
/// `total_eq`, `try_from`
///
/// `total_eq` depends on `partial_eq`, `copy` depends on
/// `clone`, so if you disable dependency, dependant
/// implementation will be disabled too, for example:
///
/// ```
/// use integral_enum::IntegralEnum;
///
/// #[derive(Debug, IntegralEnum)]
/// #[enum_disable(debug)]
/// enum Affection {
/// FellInLove,
/// HatesYou,
/// // From love to hate is one step, after all :D
/// }
///
/// assert_eq!(format!("{:?}", Affection::FellInLove), "FellInLove");
/// assert_eq!(format!("{}", Affection::HatesYou), "HatesYou");
/// // display is still available
/// ```
#[proc_macro_derive(IntegralEnum, attributes(enum_disable))]
#[proc_macro_error]
pub fn implied_integral_enum(stream: TokenStream) -> TokenStream {
inner::enum_try_from(stream, true, "enum_disable")
}
/// Strict version of the `IntegralEnum`. It implements only
/// specified implementations, for example this compiles and
/// successfully exits:
///
/// ```
/// use integral_enum::StrictIntegralEnum;
///
/// #[derive(StrictIntegralEnum)]
/// #[enum_impl(display, partial_eq, try_from)]
/// enum MusicGenre {
/// SynthWave,
/// HeavyMetal,
/// }
///
/// assert!(MusicGenre::try_from(0) == Ok(MusicGenre::SynthWave));
/// assert!(format!("{}", MusicGenre::SynthWave) == "SynthWave");
/// ```
///
/// And this will fail:
///
/// ```compile_fail
/// use integral_enum::StrictIntegralEnum;
///
/// #[derive(StrictIntegralEnum)]
/// #[enum_impl(try_from)]
/// enum MusicGenre {
/// SynthWave,
/// HeavyMetal,
/// }
///
/// assert!(MusicGenre::try_from(0) == Ok(MusicGenre::SynthWave));
/// assert!(format!("{}", MusicGenre::SynthWave) == "SynthWave");
/// ```
#[proc_macro_derive(StrictIntegralEnum, attributes(enum_impl))]
#[proc_macro_error]
pub fn strict_integral_enum(stream: TokenStream) -> TokenStream {
inner::enum_try_from(stream, false, "enum_impl")
}
mod attribute_parser;
mod discriminant_counter;
mod inner;