1 // Copyright (c) 2015 Anders Kaseorg <andersk@mit.edu>
3 // Permission is hereby granted, free of charge, to any person obtaining
4 // a copy of this software and associated documentation files (the
5 // “Software”), to deal in the Software without restriction, including
6 // without limitation the rights to use, copy, modify, merge, publish,
7 // distribute, sublicense, and/or sell copies of the Software, and to
8 // permit persons to whom the Software is furnished to do so, subject to
9 // the following conditions:
11 // The above copyright notice and this permission notice shall be
12 // included in all copies or substantial portions of the Software.
14 // THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
15 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 //! This crate exports a macro `enum_from_primitive!` that wraps an
23 //! `enum` declaration and automatically adds an implementation of
24 //! `num::FromPrimitive` (reexported here), to allow conversion from
25 //! primitive integers to the enum. It therefore provides an
26 //! alternative to the built-in `#[derive(FromPrimitive)]`, which
27 //! requires the unstable `std::num::FromPrimitive` and is disabled in
33 //! #[macro_use] extern crate enum_primitive;
34 //! extern crate num_traits;
35 //! use num_traits::FromPrimitive;
37 //! enum_from_primitive! {
38 //! #[derive(Debug, PartialEq)]
47 //! assert_eq!(FooBar::from_i32(17), Some(FooBar::Foo));
48 //! assert_eq!(FooBar::from_i32(42), Some(FooBar::Bar));
49 //! assert_eq!(FooBar::from_i32(43), Some(FooBar::Baz));
50 //! assert_eq!(FooBar::from_i32(91), None);
55 pub trait FromPrimitive: Sized {
56 fn from_i64(n: i64) -> Option<Self>;
57 fn from_u64(n: u64) -> Option<Self>;
61 pub use std::option::Option;
62 pub use num_traits::FromPrimitive;
64 /// Helper macro for internal use by `enum_from_primitive!`.
66 macro_rules! enum_from_primitive_impl_ty {
67 ($meth:ident, $ty:ty, $name:ident, $( $variant:ident )*) => {
68 #[allow(non_upper_case_globals, unused)]
69 fn $meth(n: $ty) -> $crate::Option<Self> {
70 $( if n == $name::$variant as $ty {
71 $crate::Option::Some($name::$variant)
79 /// Helper macro for internal use by `enum_from_primitive!`.
81 #[macro_use(enum_from_primitive_impl_ty)]
82 macro_rules! enum_from_primitive_impl {
83 ($name:ident, $( $variant:ident )*) => {
84 impl $crate::FromPrimitive for $name {
85 enum_from_primitive_impl_ty! { from_i64, i64, $name, $( $variant )* }
86 enum_from_primitive_impl_ty! { from_u64, u64, $name, $( $variant )* }
91 /// Wrap this macro around an `enum` declaration to get an
92 /// automatically generated implementation of `num::FromPrimitive`.
94 #[macro_use(enum_from_primitive_impl)]
95 macro_rules! enum_from_primitive {
97 $( #[$enum_attr:meta] )*
99 $( $( #[$variant_attr:meta] )* $variant:ident ),+
100 $( = $discriminator:expr, $( $( #[$variant_two_attr:meta] )* $variant_two:ident ),+ )*
105 $( $( #[$variant_attr] )* $variant ),+
106 $( = $discriminator, $( $( #[$variant_two_attr] )* $variant_two ),+ )*
108 enum_from_primitive_impl! { $name, $( $variant )+ $( $( $variant_two )+ )* }
112 $( #[$enum_attr:meta] )*
114 $( $( $( #[$variant_attr:meta] )* $variant:ident ),+ = $discriminator:expr ),*
119 $( $( $( #[$variant_attr] )* $variant ),+ = $discriminator ),*
121 enum_from_primitive_impl! { $name, $( $( $variant )+ )* }
125 $( #[$enum_attr:meta] )*
127 $( $( #[$variant_attr:meta] )* $variant:ident ),+
128 $( = $discriminator:expr, $( $( #[$variant_two_attr:meta] )* $variant_two:ident ),+ )*,
133 $( $( #[$variant_attr] )* $variant ),+
134 $( = $discriminator, $( $( #[$variant_two_attr] )* $variant_two ),+ )*,
136 enum_from_primitive_impl! { $name, $( $variant )+ $( $( $variant_two )+ )* }
140 $( #[$enum_attr:meta] )*
142 $( $( $( #[$variant_attr:meta] )* $variant:ident ),+ = $discriminator:expr ),+,
147 $( $( $( #[$variant_attr] )* $variant ),+ = $discriminator ),+,
149 enum_from_primitive_impl! { $name, $( $( $variant )+ )+ }
153 $( #[$enum_attr:meta] )*
154 pub enum $name:ident {
155 $( $( #[$variant_attr:meta] )* $variant:ident ),+
156 $( = $discriminator:expr, $( $( #[$variant_two_attr:meta] )* $variant_two:ident ),+ )*
161 $( $( #[$variant_attr] )* $variant ),+
162 $( = $discriminator, $( $( #[$variant_two_attr] )* $variant_two ),+ )*
164 enum_from_primitive_impl! { $name, $( $variant )+ $( $( $variant_two )+ )* }
168 $( #[$enum_attr:meta] )*
169 pub enum $name:ident {
170 $( $( $( #[$variant_attr:meta] )* $variant:ident ),+ = $discriminator:expr ),*
175 $( $( $( #[$variant_attr] )* $variant ),+ = $discriminator ),*
177 enum_from_primitive_impl! { $name, $( $( $variant )+ )* }
181 $( #[$enum_attr:meta] )*
182 pub enum $name:ident {
183 $( $( #[$variant_attr:meta] )* $variant:ident ),+
184 $( = $discriminator:expr, $( $( #[$variant_two_attr:meta] )* $variant_two:ident ),+ )*,
189 $( $( #[$variant_attr] )* $variant ),+
190 $( = $discriminator, $( $( #[$variant_two_attr] )* $variant_two ),+ )*,
192 enum_from_primitive_impl! { $name, $( $variant )+ $( $( $variant_two )+ )* }
196 $( #[$enum_attr:meta] )*
197 pub enum $name:ident {
198 $( $( $( #[$variant_attr:meta] )* $variant:ident ),+ = $discriminator:expr ),+,
203 $( $( $( #[$variant_attr] )* $variant ),+ = $discriminator ),+,
205 enum_from_primitive_impl! { $name, $( $( $variant )+ )+ }