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