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
//! Provides a macro to generate structures used for constant value lookup.
//!
//! ```
//! # use reword::reword;
//! reword! {
//!     enum Lang: &'static str {
//!         struct Hi {
//!             const NO = "Hei";
//!             const EN_UK | EN_US = "Hi";
//!         }
//!         struct Humor {
//!             const NO | EN_US = "Humor";
//!             const EN_UK = "Humour";
//!         }
//!     }
//! }
//!
//! let mut lang = Lang::NO;
//! assert_eq!(lang.get::<Hi>(), "Hei");
//! assert_eq!(lang.get::<Humor>(), "Humor");
//! lang = Lang::EN_UK;
//! assert_eq!(lang.get::<Hi>(), "Hi");
//! assert_eq!(lang.get::<Humor>(), "Humour");
//! lang = Lang::EN_US;
//! assert_eq!(lang.get::<Hi>(), "Hi");
//! assert_eq!(lang.get::<Humor>(), "Humor");
//! ```
//!
//! Attributes can be attached to both the `enum` and the structures generated.
//! The `Copy`, `Clone`, `Debug`, `Eq`, `PartialEq`, `Ord`, `PartialOrd`, and `Hash` traits are
//! automatically derived for the types using the derive attribute.
//! The structures generated are not exported out of its module by default.
//! Use `pub` before the`enum` keyword to export it.

#![no_std]
#![doc(html_root_url = "https://docs.rs/reword/3.0.1")]
#![deny(
    bad_style,
    bare_trait_objects,
    missing_debug_implementations,
    missing_docs,
    unused_import_braces,
    unused_qualifications,
    unsafe_code,
    unstable_features
)]

/// The macro used to generate the structures used for constant value lookup.
///
/// See the [crate level docs](index.html) for more information.
#[macro_export]
macro_rules! reword {
    (
        $(#[$enum_meta:meta])*
        $pub:vis enum $enum:ident : $T:ty {
            $(#[$key_meta:meta])*
            struct $key:ident { $($(#[$name_meta:meta])* const $($name:ident)|+ = $val:expr;)+ }
            $(
                $(#[$key2_meta:meta])*
                struct $key2:ident { $($(#[$name2_meta:meta])* const $($name2:ident)|+ = $val2:expr;)+ }
            )*
        }
    ) => {
        /// Trait used for constant value lookup.
        #[doc(hidden)]
        $pub trait Word {
            $($(#[$name_meta])* $(#[allow(non_upper_case_globals)] const $name: $T;)+)+
        }

        $(#[$enum_meta])*
        #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
        $pub enum $enum {
            $($(#[allow(non_camel_case_types)] $name,)+)+
        }

        impl $enum {
            /// Returns the value of `W`.
            #[inline]
            $pub fn get<W: Word + ?Sized>(self) -> $T {
                match self {
                    $($($enum::$name => W::$name,)+)+
                }
            }
        }

        $(#[$key_meta])*
        #[derive(Copy, Clone, Debug, Default, Hash, Ord, PartialOrd, Eq, PartialEq)]
        $pub struct $key;

        impl Word for $key {
            $($(#[$name_meta])* $(#[allow(non_upper_case_globals)] const $name: $T = $val;)+)+
        }

        $(
            $(#[$key2_meta])*
            #[derive(Copy, Clone, Debug, Default, Hash, Ord, PartialOrd, Eq, PartialEq)]
            $pub struct $key2;

            impl Word for $key2 {
                $($(#[$name2_meta])* $(#[allow(non_upper_case_globals)] const $name2: $T = $val2;)+)+
            }
        )*
    };
}