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.21" 20 //! strum_macros = "0.21" 21 //! 22 //! # You can also access strum_macros exports directly through strum using the "derive" feature 23 //! strum = { version = "0.21", features = ["derive"] } 24 //! ``` 25 //! 26 27 #![cfg_attr(docsrs, feature(doc_cfg))] 28 29 // only for documentation purposes 30 pub mod additional_attributes; 31 32 /// The ParseError enum is a collection of all the possible reasons 33 /// an enum can fail to parse from a string. 34 #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] 35 pub enum ParseError { 36 VariantNotFound, 37 } 38 39 impl std::fmt::Display for ParseError { fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error>40 fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { 41 // We could use our macro here, but this way we don't take a dependency on the 42 // macros crate. 43 match self { 44 ParseError::VariantNotFound => write!(f, "Matching variant not found"), 45 } 46 } 47 } 48 49 impl std::error::Error for ParseError { description(&self) -> &str50 fn description(&self) -> &str { 51 match self { 52 ParseError::VariantNotFound => { 53 "Unable to find a variant of the given enum matching the string given. Matching \ 54 can be extended with the Serialize attribute and is case sensitive." 55 } 56 } 57 } 58 } 59 60 /// This trait designates that an `Enum` can be iterated over. It can 61 /// be auto generated using `strum_macros` on your behalf. 62 /// 63 /// # Example 64 /// 65 /// ```rust 66 /// # use std::fmt::Debug; 67 /// // You need to bring the type into scope to use it!!! 68 /// use strum::{EnumIter, IntoEnumIterator}; 69 /// 70 /// #[derive(EnumIter, Debug)] 71 /// enum Color { 72 /// Red, 73 /// Green { range: usize }, 74 /// Blue(usize), 75 /// Yellow, 76 /// } 77 /// 78 /// // Iterate over the items in an enum and perform some function on them. 79 /// fn generic_iterator<E, F>(pred: F) 80 /// where 81 /// E: IntoEnumIterator, 82 /// F: Fn(E), 83 /// { 84 /// for e in E::iter() { 85 /// pred(e) 86 /// } 87 /// } 88 /// 89 /// generic_iterator::<Color, _>(|color| println!("{:?}", color)); 90 /// ``` 91 pub trait IntoEnumIterator: Sized { 92 type Iterator: Iterator<Item = Self>; 93 iter() -> Self::Iterator94 fn iter() -> Self::Iterator; 95 } 96 97 /// Associates additional pieces of information with an Enum. This can be 98 /// autoimplemented by deriving `EnumMessage` and annotating your variants with 99 /// `#[strum(message="...")]. 100 /// 101 /// # Example 102 /// 103 /// ```rust 104 /// # use std::fmt::Debug; 105 /// // You need to bring the type into scope to use it!!! 106 /// use strum::EnumMessage; 107 /// 108 /// #[derive(PartialEq, Eq, Debug, EnumMessage)] 109 /// enum Pet { 110 /// #[strum(message="I have a dog")] 111 /// #[strum(detailed_message="My dog's name is Spots")] 112 /// Dog, 113 /// #[strum(message="I don't have a cat")] 114 /// Cat, 115 /// } 116 /// 117 /// let my_pet = Pet::Dog; 118 /// assert_eq!("I have a dog", my_pet.get_message().unwrap()); 119 /// ``` 120 pub trait EnumMessage { get_message(&self) -> Option<&'static str>121 fn get_message(&self) -> Option<&'static str>; get_detailed_message(&self) -> Option<&'static str>122 fn get_detailed_message(&self) -> Option<&'static str>; get_serializations(&self) -> &'static [&'static str]123 fn get_serializations(&self) -> &'static [&'static str]; 124 } 125 126 /// EnumProperty is a trait that makes it possible to store additional information 127 /// with enum variants. This trait is designed to be used with the macro of the same 128 /// name in the `strum_macros` crate. Currently, the only string literals are supported 129 /// in attributes, the other methods will be implemented as additional attribute types 130 /// become stabilized. 131 /// 132 /// # Example 133 /// 134 /// ```rust 135 /// # use std::fmt::Debug; 136 /// // You need to bring the type into scope to use it!!! 137 /// use strum::EnumProperty; 138 /// 139 /// #[derive(PartialEq, Eq, Debug, EnumProperty)] 140 /// enum Class { 141 /// #[strum(props(Teacher="Ms.Frizzle", Room="201"))] 142 /// History, 143 /// #[strum(props(Teacher="Mr.Smith"))] 144 /// #[strum(props(Room="103"))] 145 /// Mathematics, 146 /// #[strum(props(Time="2:30"))] 147 /// Science, 148 /// } 149 /// 150 /// let history = Class::History; 151 /// assert_eq!("Ms.Frizzle", history.get_str("Teacher").unwrap()); 152 /// ``` 153 pub trait EnumProperty { get_str(&self, prop: &str) -> Option<&'static str>154 fn get_str(&self, prop: &str) -> Option<&'static str>; get_int(&self, _prop: &str) -> Option<usize>155 fn get_int(&self, _prop: &str) -> Option<usize> { 156 Option::None 157 } 158 get_bool(&self, _prop: &str) -> Option<bool>159 fn get_bool(&self, _prop: &str) -> Option<bool> { 160 Option::None 161 } 162 } 163 164 /// A cheap reference-to-reference conversion. Used to convert a value to a 165 /// reference value with `'static` lifetime within generic code. 166 /// #[deprecated(since="0.13.0", note="please use `#[derive(IntoStaticStr)]` instead")] 167 pub trait AsStaticRef<T> 168 where 169 T: ?Sized, 170 { as_static(&self) -> &'static T171 fn as_static(&self) -> &'static T; 172 } 173 174 /// A trait for capturing the number of variants in Enum. This trait can be autoderived by 175 /// `strum_macros`. 176 pub trait EnumCount { 177 const COUNT: usize; 178 } 179 180 /// A trait for retrieving the names of each variant in Enum. This trait can 181 /// be autoderived by `strum_macros`. 182 pub trait VariantNames { 183 /// Names of the variants of this enum 184 const VARIANTS: &'static [&'static str]; 185 } 186 187 #[cfg(feature = "derive")] 188 pub use strum_macros::*; 189 190 macro_rules! DocumentMacroRexports { 191 ($($export:ident),+) => { 192 $( 193 #[cfg(all(docsrs, feature = "derive"))] 194 #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] 195 pub use strum_macros::$export; 196 )+ 197 }; 198 } 199 200 // We actually only re-export these items individually if we're building 201 // for docsrs. You can do a weird thing where you rename the macro 202 // and then reference it through strum. The renaming feature should be deprecated now that 203 // 2018 edition is almost 2 years old, but we'll need to give people some time to do that. 204 DocumentMacroRexports! { 205 AsRefStr, 206 AsStaticStr, 207 Display, 208 EnumCount, 209 EnumDiscriminants, 210 EnumIter, 211 EnumMessage, 212 EnumProperty, 213 EnumString, 214 EnumVariantNames, 215 IntoStaticStr, 216 ToString 217 } 218