strum/
lib.rs

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.20"
20//! strum_macros = "0.20"
21//!
22//! # You can also access strum_macros exports directly through strum using the "derive" feature
23//! strum = { version = "0.20", features = ["derive"] }
24//! ```
25//!
26
27#![cfg_attr(docsrs, feature(doc_cfg))]
28
29// only for documentation purposes
30pub 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)]
35pub enum ParseError {
36    VariantNotFound,
37}
38
39impl std::fmt::Display for ParseError {
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
49impl std::error::Error for ParseError {
50    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/// ```
91pub trait IntoEnumIterator: Sized {
92    type Iterator: Iterator<Item = Self>;
93
94    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/// ```
120pub trait EnumMessage {
121    fn get_message(&self) -> Option<&str>;
122    fn get_detailed_message(&self) -> Option<&str>;
123    fn get_serializations(&self) -> &[&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/// ```
153pub trait EnumProperty {
154    fn get_str(&self, prop: &str) -> Option<&'static str>;
155    fn get_int(&self, _prop: &str) -> Option<usize> {
156        Option::None
157    }
158
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")]
167pub trait AsStaticRef<T>
168where
169    T: ?Sized,
170{
171    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`.
176pub 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`.
182pub trait VariantNames {
183    /// Names of the variants of this enum
184    const VARIANTS: &'static [&'static str];
185}
186
187#[cfg(feature = "derive")]
188pub use strum_macros::*;
189
190macro_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.
204DocumentMacroRexports! {
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}