Skip to content

Commit 44265e6

Browse files
tcrctrlcctrlv
andcommitted
Supports enum_primitive! with ToPrimitive support.
Co-Authored-By: Fredrick Brennan <[email protected]>
1 parent 49821c7 commit 44265e6

File tree

2 files changed

+192
-3
lines changed

2 files changed

+192
-3
lines changed

src/lib.rs

+142-3
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
extern crate num_traits;
5757

5858
pub use std::option::Option;
59-
pub use num_traits::FromPrimitive;
59+
pub use num_traits::{FromPrimitive, ToPrimitive};
6060

6161
/// Helper macro for internal use by `enum_from_primitive!`.
6262
#[macro_export]
@@ -73,9 +73,31 @@ macro_rules! enum_from_primitive_impl_ty {
7373
};
7474
}
7575

76+
/// Helper macro for internal use by `enum_to_primitive!`.
77+
#[macro_export]
78+
macro_rules! enum_to_primitive_impl_ty {
79+
($meth:ident, $ty:ty, $name:ident) => {
80+
#[allow(non_upper_case_globals, unused)]
81+
fn $meth(&self) -> $crate::Option<$ty> {
82+
let copy: $name = unsafe { ::std::mem::transmute_copy(self) };
83+
Some(copy as $ty)
84+
}
85+
};
86+
}
87+
88+
/// Helper macro for internal use by `enum_to_primitive!`.
89+
#[macro_export]
90+
macro_rules! enum_to_primitive_impl {
91+
($name:ident) => {
92+
impl $crate::ToPrimitive for $name {
93+
enum_to_primitive_impl_ty! { to_i64, i64, $name }
94+
enum_to_primitive_impl_ty! { to_u64, u64, $name }
95+
}
96+
};
97+
}
98+
7699
/// Helper macro for internal use by `enum_from_primitive!`.
77100
#[macro_export]
78-
#[macro_use(enum_from_primitive_impl_ty)]
79101
macro_rules! enum_from_primitive_impl {
80102
($name:ident, $( $variant:ident )*) => {
81103
impl $crate::FromPrimitive for $name {
@@ -88,7 +110,6 @@ macro_rules! enum_from_primitive_impl {
88110
/// Wrap this macro around an `enum` declaration to get an
89111
/// automatically generated implementation of `num::FromPrimitive`.
90112
#[macro_export]
91-
#[macro_use(enum_from_primitive_impl)]
92113
macro_rules! enum_from_primitive {
93114
(
94115
$( #[$enum_attr:meta] )*
@@ -194,3 +215,121 @@ macro_rules! enum_from_primitive {
194215
enum_from_primitive_impl! { $name, $( $( $variant )+ )+ }
195216
};
196217
}
218+
219+
220+
/// Wrap this macro around an `enum` declaration to get an
221+
/// automatically generated implementation of `num::FromPrimitive`.
222+
#[macro_export]
223+
macro_rules! enum_primitive {
224+
(
225+
$( #[$enum_attr:meta] )*
226+
enum $name:ident {
227+
$( $( #[$variant_attr:meta] )* $variant:ident ),+ $( = $discriminator:expr, $( $( #[$variant_two_attr:meta] )* $variant_two:ident ),+ )*
228+
}
229+
) => {
230+
$( #[$enum_attr] )*
231+
enum $name {
232+
$( $( #[$variant_attr] )* $variant ),+ $( = $discriminator, $( $( #[$variant_two_attr] )* $variant_two ),+ )*
233+
}
234+
enum_from_primitive_impl! { $name, $( $variant )+ $( $( $variant_two )+ )* }
235+
enum_to_primitive_impl! { $name }
236+
};
237+
238+
(
239+
$( #[$enum_attr:meta] )*
240+
enum $name:ident {
241+
$( $( $( #[$variant_attr:meta] )* $variant:ident ),+ = $discriminator:expr ),*
242+
}
243+
) => {
244+
$( #[$enum_attr] )*
245+
enum $name {
246+
$( $( $( #[$variant_attr] )* $variant ),+ = $discriminator ),*
247+
}
248+
enum_from_primitive_impl! { $name, $( $( $variant )+ )* }
249+
enum_to_primitive_impl! { $name }
250+
};
251+
252+
(
253+
$( #[$enum_attr:meta] )*
254+
enum $name:ident {
255+
$( $( #[$variant_attr:meta] )* $variant:ident ),+ $( = $discriminator:expr, $( $( #[$variant_two_attr:meta] )* $variant_two:ident ),+ )*,
256+
}
257+
) => {
258+
$( #[$enum_attr] )*
259+
enum $name {
260+
$( $( #[$variant_attr] )* $variant ),+ $( = $discriminator, $( $( #[$variant_two_attr] )* $variant_two ),+ )*,
261+
}
262+
enum_from_primitive_impl! { $name, $( $variant )+ $( $( $variant_two )+ )* }
263+
enum_to_primitive_impl! { $name }
264+
};
265+
266+
(
267+
$( #[$enum_attr:meta] )*
268+
enum $name:ident {
269+
$( $( $( #[$variant_attr:meta] )* $variant:ident ),+ = $discriminator:expr ),+,
270+
}
271+
) => {
272+
$( #[$enum_attr] )*
273+
enum $name {
274+
$( $( $( #[$variant_attr] )* $variant ),+ = $discriminator ),+,
275+
}
276+
enum_from_primitive_impl! { $name, $( $( $variant )+ )+ }
277+
enum_to_primitive_impl! { $name }
278+
};
279+
280+
(
281+
$( #[$enum_attr:meta] )*
282+
pub enum $name:ident {
283+
$( $( #[$variant_attr:meta] )* $variant:ident ),+ $( = $discriminator:expr, $( $( #[$variant_two_attr:meta] )* $variant_two:ident ),+ )*
284+
}
285+
) => {
286+
$( #[$enum_attr] )*
287+
pub enum $name {
288+
$( $( #[$variant_attr] )* $variant ),+ $( = $discriminator, $( $( #[$variant_two_attr] )* $variant_two ),+ )*
289+
}
290+
enum_from_primitive_impl! { $name, $( $variant )+ $( $( $variant_two )+ )* }
291+
enum_to_primitive_impl! { $name }
292+
};
293+
294+
(
295+
$( #[$enum_attr:meta] )*
296+
pub enum $name:ident {
297+
$( $( $( #[$variant_attr:meta] )* $variant:ident ),+ = $discriminator:expr ),*
298+
}
299+
) => {
300+
$( #[$enum_attr] )*
301+
pub enum $name {
302+
$( $( $( #[$variant_attr] )* $variant ),+ = $discriminator ),*
303+
}
304+
enum_from_primitive_impl! { $name, $( $( $variant )+ )* }
305+
enum_to_primitive_impl! { $name }
306+
};
307+
308+
(
309+
$( #[$enum_attr:meta] )*
310+
pub enum $name:ident {
311+
$( $( #[$variant_attr:meta] )* $variant:ident ),+ $( = $discriminator:expr, $( $( #[$variant_two_attr:meta] )* $variant_two:ident ),+ )*,
312+
}
313+
) => {
314+
$( #[$enum_attr] )*
315+
pub enum $name {
316+
$( $( #[$variant_attr] )* $variant ),+ $( = $discriminator, $( $( #[$variant_two_attr] )* $variant_two ),+ )*,
317+
}
318+
enum_from_primitive_impl! { $name, $( $variant )+ $( $( $variant_two )+ )* }
319+
enum_to_primitive_impl! { $name }
320+
};
321+
322+
(
323+
$( #[$enum_attr:meta] )*
324+
pub enum $name:ident {
325+
$( $( $( #[$variant_attr:meta] )* $variant:ident ),+ = $discriminator:expr ),+,
326+
}
327+
) => {
328+
$( #[$enum_attr] )*
329+
pub enum $name {
330+
$( $( $( #[$variant_attr] )* $variant ),+ = $discriminator ),+,
331+
}
332+
enum_from_primitive_impl! { $name, $( $( $variant )+ )+ }
333+
enum_to_primitive_impl! { $name }
334+
};
335+
}

tests/tests.rs

+50
Original file line numberDiff line numberDiff line change
@@ -233,3 +233,53 @@ fn documented() {
233233
assert_eq!(Documented::from_i32(17), Some(Documented::A));
234234
assert_eq!(Documented::from_i32(91), None);
235235
}
236+
237+
#[test]
238+
fn to_primitive() {
239+
use ep::ToPrimitive;
240+
241+
mod top {
242+
enum_primitive! {
243+
#[derive(Debug, PartialEq)]
244+
#[repr(u64)]
245+
pub enum EnumU64 {
246+
A = 0xdeadbeefdeadbeef,
247+
B = 0x0,
248+
}
249+
}
250+
251+
enum_primitive! {
252+
#[derive(Debug, PartialEq)]
253+
#[repr(u32)]
254+
pub enum EnumU32 {
255+
A = 0xdeadbeef,
256+
B = 0x0,
257+
}
258+
}
259+
260+
enum_primitive! {
261+
#[derive(Debug, PartialEq)]
262+
#[repr(u16)]
263+
pub enum EnumU16 {
264+
A = 0xdead,
265+
B = 0x0,
266+
}
267+
}
268+
269+
enum_primitive! {
270+
#[derive(Debug, PartialEq)]
271+
#[repr(u8)]
272+
pub enum EnumU8 {
273+
A = 0xde,
274+
B = 0x0,
275+
}
276+
}
277+
}
278+
279+
println!("what {:?}", top::EnumU8::A.to_u8());
280+
281+
assert_eq!(0xdeadbeefdeadbeef, top::EnumU64::A.to_u64().unwrap());
282+
assert_eq!(0xdeadbeef, top::EnumU32::A.to_u32().unwrap());
283+
assert_eq!(0xdead, top::EnumU16::A.to_u16().unwrap());
284+
assert_eq!(0xde, top::EnumU8::A.to_u8().unwrap());
285+
}

0 commit comments

Comments
 (0)