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 118 119 120
//! Macro for generating pseudo-enums for type-level programming. //! This is somewhat like https://github.com/fmease/tylift but implemented with `macro_rules!` syntax //! ``` //! # use enum_to_types::enum_to_types; //! # use std::marker::PhantomData; //! enum_to_types!(AccessLevel; User, Admin); //! //! struct DataStorage<T: AccessLevel::AccessLevel>(i32, PhantomData<T>); //! //! impl<T: AccessLevel::AccessLevel> DataStorage<T> { //! fn new(i: i32) -> Self { //! Self(i, PhantomData) //! } //! } //! //! trait ReadStorage<T: AccessLevel::AccessLevel> { //! fn read(&self) -> i32; //! } //! //! impl ReadStorage<AccessLevel::Admin> for DataStorage<AccessLevel::User> { //! fn read(&self) -> i32 { //! self.0 //! } //! } //! //! impl ReadStorage<AccessLevel::User> for DataStorage<AccessLevel::User> { //! fn read(&self) -> i32 { //! self.0 //! } //! } //! //! impl ReadStorage<AccessLevel::Admin> for DataStorage<AccessLevel::Admin> { //! fn read(&self) -> i32 { //! self.0 //! } //! } //! //! impl ReadStorage<AccessLevel::User> for DataStorage<AccessLevel::Admin> { //! fn read(&self) -> i32 { //! panic!("You have no rights to read this"); //! } //! } //! //! fn main() { //! let storage = DataStorage::<AccessLevel::Admin>::new(1); //! assert_eq!(<DataStorage::<AccessLevel::Admin> as ReadStorage<AccessLevel::Admin>>::read(&storage), 1); //! let storage = DataStorage::<AccessLevel::User>::new(5); //! assert_eq!(<DataStorage::<AccessLevel::User> as ReadStorage<AccessLevel::User>>::read(&storage), 5); //! // reading storage with `AccessLevel::Admin` by user will cause panic //! } //! ``` //! This may look very verbose but it gives a lot of flexibility. //! Also, other examples can look less verbose. /// Macro for generating pseudo-enums for type-level programming. /// This is somewhat like https://github.com/fmease/tylift but implemented with `macro_rules!` syntax /// ``` /// # use enum_to_types::enum_to_types; /// # use std::marker::PhantomData; /// enum_to_types!(AccessLevel; User, Admin); /// /// struct DataStorage<T: AccessLevel::AccessLevel>(i32, PhantomData<T>); /// /// impl<T: AccessLevel::AccessLevel> DataStorage<T> { /// fn new(i: i32) -> Self { /// Self(i, PhantomData) /// } /// } /// /// trait ReadStorage<T: AccessLevel::AccessLevel> { /// fn read(&self) -> i32; /// } /// /// impl ReadStorage<AccessLevel::Admin> for DataStorage<AccessLevel::User> { /// fn read(&self) -> i32 { /// self.0 /// } /// } /// /// impl ReadStorage<AccessLevel::User> for DataStorage<AccessLevel::User> { /// fn read(&self) -> i32 { /// self.0 /// } /// } /// /// impl ReadStorage<AccessLevel::Admin> for DataStorage<AccessLevel::Admin> { /// fn read(&self) -> i32 { /// self.0 /// } /// } /// /// impl ReadStorage<AccessLevel::User> for DataStorage<AccessLevel::Admin> { /// fn read(&self) -> i32 { /// panic!("You have no rights to read this"); /// } /// } /// /// fn main() { /// let storage = DataStorage::<AccessLevel::Admin>::new(1); /// assert_eq!(<DataStorage::<AccessLevel::Admin> as ReadStorage<AccessLevel::Admin>>::read(&storage), 1); /// let storage = DataStorage::<AccessLevel::User>::new(5); /// assert_eq!(<DataStorage::<AccessLevel::User> as ReadStorage<AccessLevel::User>>::read(&storage), 5); /// // reading storage with `AccessLevel::Admin` by user will cause panic /// } /// ``` /// This may look very verbose but it gives a lot of flexibility. /// Also, other examples can look less verbose. #[macro_export] macro_rules! enum_to_types { ($name:ident; $($variant:ident),+) => { pub mod $name { pub trait $name {} $( #[derive(Debug, Ord, Hash, Eq, PartialOrd, PartialEq)] pub struct $variant; impl $name for $variant {} )+ } }; }