wrapped_enum 0.1.3

Useful macro to wrap existing types in an enum (common use for quick error handling)
Documentation
//! wrapped_enum! - Wrap multiple types into an Enum
//!
//! This is useful when returning multiple types.
//! simply to just work on an enum of known types.
//!
//! Documentation is required when using public enums
//!
//! ```
//! # #[macro_use] extern crate wrapped_enum;
//! # use std::io;
//! #[derive(Debug)]
//! pub enum TestError {
//!     ErrorA,
//!     ErrorB(u8, u16),
//!     ErrorC(String),
//! }
//!
//! wrapped_enum!{
//!     #[derive(Debug)]
//!     /// Document your pub enums
//!     pub enum DocumentedEnum {
//!         /// Variants too
//!         Io(io::Error),
//!         /// Documentation is required for pub enums
//!         Test(TestError),
//!         /// Unknown error
//!         Unknown(()),
//!     }
//! }
//!
//! wrapped_enum!{
//!     #[derive(Debug, Eq, PartialEq)]
//!     /// You can't document private variants
//!     enum UndocumentedEnum {
//!         // However, there is nothing wrong with normal comments
//!         Byte(u8),        // 00-FF
//!         DoubleByte(u16), // 0000-FFFF
//!     }
//! }
//! 
//! # fn main() {
//! assert!(UndocumentedEnum::from(0u8) == UndocumentedEnum::Byte(0));
//! assert!(UndocumentedEnum::from(0u16) == UndocumentedEnum::DoubleByte(0));
//! # }
//! ```

#[macro_export]
macro_rules! wrapped_enum {
    ($(#[$attr:meta])*
     pub enum $enum_name:ident {
         $($(#[$variant_attr:meta])+
         $enum_variant_name:ident($ty:ty)),+
         $(,)*
     }
    ) => (
        $(#[$attr])*
        pub enum $enum_name { $($(#[$variant_attr])+ $enum_variant_name($ty)),+ }
        $(impl From<$ty> for $enum_name {
            fn from (ty: $ty) -> Self {
                $enum_name::$enum_variant_name(ty)
            }
        })+
    );
    ($(#[$attr:meta])*
     enum $enum_name:ident {
         $($enum_variant_name:ident($ty:ty)),+
         $(,)*
     }
    ) => (
        $(#[$attr])*
        enum $enum_name { $($enum_variant_name($ty)),+ }
        $(impl From<$ty> for $enum_name {
            fn from (ty: $ty) -> Self {
                $enum_name::$enum_variant_name(ty)
            }
        })+
    );
}

#[cfg(test)]
mod test {
    #[derive(Debug)]
    #[allow(dead_code)]
    pub enum CommunicationError {
        HumanError(Human, ErrorAction),
        UnknownError,
    }

    #[derive(Debug)]
    #[allow(dead_code)]
    pub enum ErrorAction {
        AttemptedToStealSecrets,
        StoleSecrets,
    }

    #[derive(Debug)]
    #[allow(dead_code)]
    pub enum Human {
        Alice, // Good
        Bob,   // Good
        Carol, // Good
        Dave,  // Good
        Eve,   // Bad
    }

    wrapped_enum!{
        #[derive(Debug)]
        /// Document your pub enums
        pub enum TestError {
//          /// Variants too
//          Io(io::Error),
            /// Documentation is required for pub enums
            Test(CommunicationError),
            /// Unknown error
            Unknown(()),
        }
    }

    wrapped_enum!{
        #[derive(Debug)]
        /// You can't document private variants
        enum UndocumentedEnum {
            // However, there is nothing wrong with normal comments
            Byte(u8),        // 00-FF
            DoubleByte(u16), // 0000-FFFF
        }
    }

    #[test]
    fn eve_intercept_alice_and_bobs_communication() {
        let error: Result<(), CommunicationError> =
            Err(CommunicationError::HumanError(Human::Eve,
                                               ErrorAction::AttemptedToStealSecrets));

        let result: Result<(), TestError> = error.map_err(From::from);

        assert!(result.is_err());
    }
}