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