1 //! # Strum 2 //! 3 //! [![Build Status](https://travis-ci.org/Peternator7/strum.svg?branch=master)](https://travis-ci.org/Peternator7/strum) 4 //! [![Latest Version](https://img.shields.io/crates/v/strum.svg)](https://crates.io/crates/strum) 5 //! [![Rust Documentation](https://docs.rs/strum/badge.svg)](https://docs.rs/strum) 6 //! 7 //! Strum is a set of macros and traits for working with 8 //! enums and strings easier in Rust. 9 //! 10 //! The full version of the README can be found on [Github](https://github.com/Peternator7/strum). 11 //! 12 //! # Including Strum in Your Project 13 //! 14 //! Import strum and strum_macros into your project by adding the following lines to your 15 //! Cargo.toml. Strum_macros contains the macros needed to derive all the traits in Strum. 16 //! 17 //! ```toml 18 //! [dependencies] 19 //! strum = "0.18.0" 20 //! strum_macros = "0.18.0" 21 //! ``` 22 //! 23 //! And add these lines to the root of your project, either lib.rs or main.rs. 24 //! 25 //! ```rust 26 //! // Strum contains all the trait definitions 27 //! extern crate strum; 28 //! #[macro_use] 29 //! extern crate strum_macros; 30 //! # fn main() {} 31 //! ``` 32 //! 33 //! # Strum Macros 34 //! 35 //! Strum has implemented the following macros: 36 //! 37 //! | Macro | Description | 38 //! | --- | ----------- | 39 //! | [EnumString] | Converts strings to enum variants based on their name | 40 //! | [Display] | Converts enum variants to strings | 41 //! | [AsRefStr] | Converts enum variants to `&'static str` | 42 //! | [IntoStaticStr] | Implements `From<MyEnum> for &'static str` on an enum | 43 //! | [EnumVariantNames] | Implements Strum::VariantNames which adds an associated constant `VARIANTS` which is an array of discriminant names | 44 //! | [EnumIter] | Creates a new type that iterates of the variants of an enum. | 45 //! | [EnumProperty] | Add custom properties to enum variants. | 46 //! | [EnumMessage] | Add a verbose message to an enum variant. | 47 //! | [EnumDiscriminants] | Generate a new type with only the discriminant names. | 48 //! | [EnumCount] | Add a constant `usize` equal to the number of variants. | 49 //! 50 //! [EnumString]: https://github.com/Peternator7/strum/wiki/Derive-EnumString 51 //! [Display]: https://github.com/Peternator7/strum/wiki/Derive-Display 52 //! [AsRefStr]: https://github.com/Peternator7/strum/wiki/Derive-AsRefStr 53 //! [IntoStaticStr]: https://github.com/Peternator7/strum/wiki/Derive-IntoStaticStr 54 //! [EnumVariantNames]: https://github.com/Peternator7/strum/wiki/Derive-EnumVariantNames 55 //! [EnumIter]: https://github.com/Peternator7/strum/wiki/Derive-EnumIter 56 //! [EnumProperty]: https://github.com/Peternator7/strum/wiki/Derive-EnumProperty 57 //! [EnumMessage]: https://github.com/Peternator7/strum/wiki/Derive-EnumMessage 58 //! [EnumDiscriminants]: https://github.com/Peternator7/strum/wiki/Derive-EnumDiscriminants 59 //! [EnumCount]: https://github.com/Peternator7/strum/wiki/Derive-EnumCount 60 61 /// The ParseError enum is a collection of all the possible reasons 62 /// an enum can fail to parse from a string. 63 #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] 64 pub enum ParseError { 65 VariantNotFound, 66 } 67 68 impl std::fmt::Display for ParseError { fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error>69 fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { 70 // We could use our macro here, but this way we don't take a dependency on the 71 // macros crate. 72 match self { 73 ParseError::VariantNotFound => write!(f, "Matching variant not found"), 74 } 75 } 76 } 77 78 impl std::error::Error for ParseError { description(&self) -> &str79 fn description(&self) -> &str { 80 match self { 81 ParseError::VariantNotFound => { 82 "Unable to find a variant of the given enum matching the string given. Matching \ 83 can be extended with the Serialize attribute and is case sensitive." 84 } 85 } 86 } 87 } 88 89 /// This trait designates that an `Enum` can be iterated over. It can 90 /// be auto generated using `strum_macros` on your behalf. 91 /// 92 /// # Example 93 /// 94 /// ```rust 95 /// # extern crate strum; 96 /// # #[macro_use] extern crate strum_macros; 97 /// # use std::fmt::Debug; 98 /// // You need to bring the type into scope to use it!!! 99 /// use strum::IntoEnumIterator; 100 /// 101 /// #[derive(EnumIter,Debug)] 102 /// enum Color { 103 /// Red, 104 /// Green { range:usize }, 105 /// Blue(usize), 106 /// Yellow, 107 /// } 108 /// 109 /// // Iterate over the items in an enum and perform some function on them. 110 /// fn generic_iterator<E, F>(pred: F) 111 /// where 112 /// E: IntoEnumIterator, 113 /// F: Fn(E), 114 /// { 115 /// for e in E::iter() { 116 /// pred(e) 117 /// } 118 /// } 119 /// 120 /// fn main() { 121 /// generic_iterator::<Color, _>(|color| println!("{:?}", color)); 122 /// } 123 /// ``` 124 pub trait IntoEnumIterator: Sized { 125 type Iterator: Iterator<Item = Self>; 126 iter() -> Self::Iterator127 fn iter() -> Self::Iterator; 128 } 129 130 /// Associates additional pieces of information with an Enum. This can be 131 /// autoimplemented by deriving `EnumMessage` and annotating your variants with 132 /// `#[strum(message="...")]. 133 /// 134 /// # Example 135 /// 136 /// ```rust 137 /// # extern crate strum; 138 /// # #[macro_use] extern crate strum_macros; 139 /// # use std::fmt::Debug; 140 /// // You need to bring the type into scope to use it!!! 141 /// use strum::EnumMessage; 142 /// 143 /// #[derive(PartialEq, Eq, Debug, EnumMessage)] 144 /// enum Pet { 145 /// #[strum(message="I have a dog")] 146 /// #[strum(detailed_message="My dog's name is Spots")] 147 /// Dog, 148 /// #[strum(message="I don't have a cat")] 149 /// Cat, 150 /// } 151 /// 152 /// fn main() { 153 /// let my_pet = Pet::Dog; 154 /// assert_eq!("I have a dog", my_pet.get_message().unwrap()); 155 /// } 156 /// ``` 157 pub trait EnumMessage { get_message(&self) -> Option<&str>158 fn get_message(&self) -> Option<&str>; get_detailed_message(&self) -> Option<&str>159 fn get_detailed_message(&self) -> Option<&str>; get_serializations(&self) -> &[&str]160 fn get_serializations(&self) -> &[&str]; 161 } 162 163 /// EnumProperty is a trait that makes it possible to store additional information 164 /// with enum variants. This trait is designed to be used with the macro of the same 165 /// name in the `strum_macros` crate. Currently, the only string literals are supported 166 /// in attributes, the other methods will be implemented as additional attribute types 167 /// become stabilized. 168 /// 169 /// # Example 170 /// 171 /// ```rust 172 /// # extern crate strum; 173 /// # #[macro_use] extern crate strum_macros; 174 /// # use std::fmt::Debug; 175 /// // You need to bring the type into scope to use it!!! 176 /// use strum::EnumProperty; 177 /// 178 /// #[derive(PartialEq, Eq, Debug, EnumProperty)] 179 /// enum Class { 180 /// #[strum(props(Teacher="Ms.Frizzle", Room="201"))] 181 /// History, 182 /// #[strum(props(Teacher="Mr.Smith"))] 183 /// #[strum(props(Room="103"))] 184 /// Mathematics, 185 /// #[strum(props(Time="2:30"))] 186 /// Science, 187 /// } 188 /// 189 /// fn main() { 190 /// let history = Class::History; 191 /// assert_eq!("Ms.Frizzle", history.get_str("Teacher").unwrap()); 192 /// } 193 /// ``` 194 pub trait EnumProperty { get_str(&self, &str) -> Option<&'static str>195 fn get_str(&self, &str) -> Option<&'static str>; get_int(&self, &str) -> Option<usize>196 fn get_int(&self, &str) -> Option<usize> { 197 Option::None 198 } 199 get_bool(&self, &str) -> Option<bool>200 fn get_bool(&self, &str) -> Option<bool> { 201 Option::None 202 } 203 } 204 205 /// A cheap reference-to-reference conversion. Used to convert a value to a 206 /// reference value with `'static` lifetime within generic code. 207 /// #[deprecated(since="0.13.0", note="please use `#[derive(IntoStaticStr)]` instead")] 208 pub trait AsStaticRef<T> 209 where 210 T: ?Sized, 211 { as_static(&self) -> &'static T212 fn as_static(&self) -> &'static T; 213 } 214 215 /// A trait for capturing the number of variants in Enum. This trait can be autoderived by 216 /// `strum_macros`. 217 pub trait EnumCount { count() -> usize218 fn count() -> usize; 219 } 220 221 /// A trait for retrieving the names of each variant in Enum. This trait can 222 /// be autoderived by `strum_macros`. 223 pub trait VariantNames { 224 /// Names of the variants of this enum 225 const VARIANTS: &'static [&'static str]; 226 } 227 228 #[cfg(feature = "derive")] 229 #[allow(unused_imports)] 230 #[macro_use] 231 extern crate strum_macros; 232 233 #[cfg(feature = "derive")] 234 #[doc(hidden)] 235 pub use strum_macros::*; 236