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