Skip to content

Commit 995deaa

Browse files
tcrctrlcctrlv
andcommitted
Supports enum_primitive! with ToPrimitive support.
Co-Authored-By: Fredrick Brennan <[email protected]>
1 parent 945a2dc commit 995deaa

File tree

2 files changed

+192
-1
lines changed

2 files changed

+192
-1
lines changed

src/lib.rs

Lines changed: 142 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757
extern crate num_traits;
5858

5959
pub use core::option::Option;
60-
pub use num_traits::FromPrimitive;
60+
pub use num_traits::{FromPrimitive, ToPrimitive};
6161

6262
/// Helper macro for internal use by `enum_from_primitive!`.
6363
#[macro_export]
@@ -74,6 +74,29 @@ macro_rules! enum_from_primitive_impl_ty {
7474
};
7575
}
7676

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

tests/tests.rs

Lines changed: 50 additions & 0 deletions
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)