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