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
105
106
107
108
109
110
111
112
113
114
115
116
117
#![no_std]

/*! This crate allows for the creation
  of type-level values. Any value can
  be type-level as long as it can be
  initialized as a constant. All
  type-level values implement the
  TypeVal trait, and so can be provided
  as type parameters.
  
  ## Example
  
  ```rust
  #[macro_use]
  extern crate type_val;
  use type_val::TypeVal;

  use std::marker::PhantomData;

  fn main() {
      let mut adder = Adder::<Two, One>::new();
      
      assert_eq!(adder.sum, 2);
      
      adder.add();
      
      assert_eq!(adder.sum, 3);
  }
  
  def_type_val! {
      type One: u32 = 1;
      type Two: u32 = 2;
  }
  
  struct Adder<S, I> {
      sum: u32,
      _marker: PhantomData<(S, I)>,
  }
  
  impl <S, I> Adder<S, I>
      where S: TypeVal<u32>,
            I: TypeVal<u32>,
  {
      fn new() -> Adder<S, I> {
          Adder {
              // Get the value of S
              sum: S::VAL,
              _marker: PhantomData,
          }
      }
      
      fn add(&mut self) {
          // Get the value of I
          self.sum += I::VAL;
      }
  }
  ```
!*/

/// A trait implemented by type-level values.
pub trait TypeVal<T> {
    /// The value held.
    const VAL: T;
}

/** This macro is used to implement the
  TypeVal trait. Any number of values
  can be initialized with a single
  invocation. Items prefixed by `pub`
  are public. Attributes to be applied
  to items in a block, including doc
  comments, should go above their
  targets.
 
  ## Example
 
  ```rust
  def_type_val! {
      type One: i32 = 1;
      #[derive(Clone, Copy)]
      type True: bool = true;
      /// Negative one
      pub type NegOne: i32 = -1;
      pub type False: bool = false;
   }
 
  println!("One = {}, True = {}, NegOne = {}, False = {}",
      One::VAL,
      True::VAL,
      NegOne::VAL,
      False::VAL);
  ```
**/
#[macro_export]
macro_rules! def_type_val {
    {$(#[$attr:meta])* type $name:ident: $type:ty = $value:expr; $($next:tt)*} => {
        $(#[$attr])*
        struct $name;
        
        impl $crate::TypeVal<$type> for $name {
            const VAL: $type = $value;
        }
        
        def_type_val!($($next)*);
    };
    {$(#[$attr:meta])* pub type $name:ident: $type:ty = $value:expr; $($next:tt)*} => {
        $(#[$attr])*
        pub struct $name;
        
        impl $crate::TypeVal<$type> for $name {
            const VAL: $type = $value;
        }
        
        def_type_val!($($next)*);
    };
    () => {};
}