Skip to content

Commit c403d0e

Browse files
committed
Initial commit of enum_primitive
Signed-off-by: Anders Kaseorg <[email protected]>
0 parents  commit c403d0e

File tree

6 files changed

+230
-0
lines changed

6 files changed

+230
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
target
2+
Cargo.lock

.travis.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
language: rust
2+
3+
rust:
4+
- nightly
5+
- 1.0.0-beta

Cargo.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[package]
2+
name = "enum_primitive"
3+
version = "0.0.1"
4+
license = "MIT"
5+
description = "Macro to generate num::FromPrimitive instances for enum that works in Rust 1.0"
6+
authors = ["Anders Kaseorg <[email protected]>"]
7+
repository = "https://github.com/andersk/enum_primitive-rs.git"
8+
homepage = "https://github.com/andersk/enum_primitive-rs"
9+
10+
[dependencies]
11+
num = "0.1"

LICENSE

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
Copyright (c) 2015 Anders Kaseorg <[email protected]>
2+
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:
10+
11+
The above copyright notice and this permission notice shall be
12+
included in all copies or substantial portions of the Software.
13+
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.

README.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
This crate exports a macro `enum_from_primitive!` that wraps an
2+
`enum` declaration and automatically adds an implementation of
3+
`num::FromPrimitive` (reexported here), to allow conversion from
4+
primitive integers to the enum. It therefore provides an
5+
alternative to the built-in `#[derive(FromPrimitive)]`, which
6+
requires the unstable `std::num::FromPrimitive` and is disabled in
7+
Rust 1.0.
8+
9+
The current implementation requires all variants of the num to
10+
have an explicit discriminator value. This restriction may be
11+
relaxed in future versions.
12+
13+
## Usage
14+
15+
Add the following to your `Cargo.toml` file:
16+
17+
```
18+
[dependencies]
19+
enum_primitive = "*"
20+
```
21+
22+
Import the crate using `#[macro_use] extern crate enum_primitive`, and
23+
wrap your `enum` declaration inside the `enum_from_primitive!` macro.
24+
25+
## Example
26+
27+
```rust
28+
#[macro_use] extern crate enum_primitive;
29+
extern crate num;
30+
use num::FromPrimitive;
31+
32+
enum_from_primitive! {
33+
#[derive(Debug, PartialEq)]
34+
enum FooBar {
35+
Foo = 17,
36+
Bar = 42,
37+
}
38+
}
39+
40+
fn main() {
41+
assert_eq!(FooBar::from_i32(17), Some(FooBar::Foo));
42+
assert_eq!(FooBar::from_i32(42), Some(FooBar::Bar));
43+
assert_eq!(FooBar::from_i32(91), None);
44+
}
45+
```

src/lib.rs

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
// Copyright (c) 2015 Anders Kaseorg <[email protected]>
2+
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:
10+
11+
// The above copyright notice and this permission notice shall be
12+
// included in all copies or substantial portions of the Software.
13+
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.
21+
22+
23+
//! This crate exports a macro `enum_from_primitive!` that wraps an
24+
//! `enum` declaration and automatically adds an implementation of
25+
//! `num::FromPrimitive` (reexported here), to allow conversion from
26+
//! primitive integers to the enum. It therefore provides an
27+
//! alternative to the built-in `#[derive(FromPrimitive)]`, which
28+
//! requires the unstable `std::num::FromPrimitive` and is disabled in
29+
//! Rust 1.0.
30+
//!
31+
//! The current implementation requires all variants of the num to
32+
//! have an explicit discriminator value. This restriction may be
33+
//! relaxed in future versions.
34+
//!
35+
//! # Example
36+
//!
37+
//! ```
38+
//! #[macro_use] extern crate enum_primitive;
39+
//! extern crate num;
40+
//! use num::FromPrimitive;
41+
//!
42+
//! enum_from_primitive! {
43+
//! #[derive(Debug, PartialEq)]
44+
//! enum FooBar {
45+
//! Foo = 17,
46+
//! Bar = 42,
47+
//! }
48+
//! }
49+
//!
50+
//! fn main() {
51+
//! assert_eq!(FooBar::from_i32(17), Some(FooBar::Foo));
52+
//! assert_eq!(FooBar::from_i32(42), Some(FooBar::Bar));
53+
//! assert_eq!(FooBar::from_i32(91), None);
54+
//! }
55+
//! ```
56+
57+
58+
extern crate num;
59+
60+
pub use num::FromPrimitive;
61+
62+
/// Helper macro for internal use by `enum_from_primitive!`.
63+
#[macro_export]
64+
macro_rules! enum_from_primitive_impl_ty {
65+
($meth:ident, $ty:ty, $name:ident, $( $variant:ident ),*) => {
66+
#[allow(non_upper_case_globals)]
67+
fn $meth(n: $ty) -> ::std::option::Option<Self> {
68+
$( const $variant: $ty = $name::$variant as $ty; )*
69+
match n {
70+
$( $variant => ::std::option::Option::Some($name::$variant), )*
71+
_ => ::std::option::Option::None,
72+
}
73+
}
74+
}
75+
}
76+
77+
/// Helper macro for internal use by `enum_from_primitive!`.
78+
#[macro_export]
79+
#[macro_use(enum_from_primitive_impl_ty)]
80+
macro_rules! enum_from_primitive_impl {
81+
($name:ident, $( $variant:ident ),*) => {
82+
impl ::num::FromPrimitive for $name {
83+
enum_from_primitive_impl_ty! { from_i64, i64, $name, $( $variant ),* }
84+
enum_from_primitive_impl_ty! { from_u64, u64, $name, $( $variant ),* }
85+
}
86+
}
87+
}
88+
89+
/// Wrap this macro around an `enum` declaration to get an
90+
/// automatically generated implementation of `num::FromPrimitive`.
91+
#[macro_export]
92+
#[macro_use(enum_from_primitive_impl)]
93+
macro_rules! enum_from_primitive {
94+
(
95+
$( #[$enum_attr:meta] )*
96+
enum $name:ident {
97+
$( $( #[$variant_attr:meta] )* $variant:ident = $discriminator:expr ),*
98+
}
99+
) => {
100+
$( #[$enum_attr] )*
101+
enum $name {
102+
$( $( #[$variant_attr] )* $variant = $discriminator ),*
103+
}
104+
enum_from_primitive_impl! { $name, $($variant),* }
105+
};
106+
107+
(
108+
$( #[$enum_attr:meta] )*
109+
enum $name:ident {
110+
$( $( #[$variant_attr:meta] )* $variant:ident = $discriminator:expr ),*,
111+
}
112+
) => {
113+
enum_from_primitive! {
114+
$( #[$enum_attr] )*
115+
enum $name {
116+
$( $( #[$variant_attr] )* $variant = $discriminator ),*
117+
}
118+
}
119+
};
120+
121+
(
122+
$( #[$enum_attr:meta] )*
123+
pub enum $name:ident {
124+
$( $( #[$variant_attr:meta] )* $variant:ident = $discriminator:expr ),*
125+
}
126+
) => {
127+
$( #[$enum_attr] )*
128+
pub enum $name {
129+
$( $( #[$variant_attr] )* $variant = $discriminator ),*
130+
}
131+
enum_from_primitive_impl! { $name, $( $variant ),* }
132+
};
133+
134+
(
135+
$( #[$enum_attr:meta] )*
136+
pub enum $name:ident {
137+
$( $( #[$variant_attr:meta] )* $variant:ident = $discriminator:expr ),*,
138+
}
139+
) => {
140+
enum_from_primitive! {
141+
$( #[$enum_attr] )*
142+
pub enum $name {
143+
$( $( #[$variant_attr] )* $variant = $discriminator ),*
144+
}
145+
}
146+
};
147+
}

0 commit comments

Comments
 (0)