1 use ::num_enum::FromPrimitive;
2 
3 // Guard against https://github.com/illicitonion/num_enum/issues/27
4 mod alloc {}
5 mod core {}
6 mod num_enum {}
7 mod std {}
8 
9 macro_rules! has_from_primitive_number {
10     ( $type:ty ) => {
11         paste::paste! {
12             #[test]
13             fn [<has_from_primitive_number_ $type>]() {
14                 #[derive(Debug, Eq, PartialEq, FromPrimitive)]
15                 #[repr($type)]
16                 enum Enum {
17                     Zero = 0,
18                     #[num_enum(default)]
19                     NonZero = 1,
20                 }
21 
22                 let zero = Enum::from_primitive(0 as $type);
23                 assert_eq!(zero, Enum::Zero);
24 
25                 let one = Enum::from_primitive(1 as $type);
26                 assert_eq!(one, Enum::NonZero);
27 
28                 let two = Enum::from_primitive(2 as $type);
29                 assert_eq!(two, Enum::NonZero);
30             }
31         }
32     };
33 }
34 
35 has_from_primitive_number!(u8);
36 has_from_primitive_number!(u16);
37 has_from_primitive_number!(u32);
38 has_from_primitive_number!(u64);
39 has_from_primitive_number!(usize);
40 has_from_primitive_number!(i8);
41 has_from_primitive_number!(i16);
42 has_from_primitive_number!(i32);
43 has_from_primitive_number!(i64);
44 has_from_primitive_number!(isize);
45 // repr with 128-bit type is unstable
46 // has_from_primitive_number!(u128);
47 // has_from_primitive_number!(i128);
48 
49 #[test]
has_from_primitive_number_standard_default_attribute()50 fn has_from_primitive_number_standard_default_attribute() {
51     #[derive(Debug, Eq, PartialEq, FromPrimitive)]
52     #[repr(u8)]
53     enum Enum {
54         Zero = 0,
55         #[default]
56         NonZero = 1,
57     }
58 
59     let zero = Enum::from_primitive(0_u8);
60     assert_eq!(zero, Enum::Zero);
61 
62     let one = Enum::from_primitive(1_u8);
63     assert_eq!(one, Enum::NonZero);
64 
65     let two = Enum::from_primitive(2_u8);
66     assert_eq!(two, Enum::NonZero);
67 }
68 
69 #[test]
from_primitive_number()70 fn from_primitive_number() {
71     #[derive(Debug, Eq, PartialEq, FromPrimitive)]
72     #[repr(u8)]
73     enum Enum {
74         #[num_enum(default)]
75         Whatever = 0,
76     }
77 
78     // #[derive(FromPrimitive)] generates implementations for the following traits:
79     //
80     // - `FromPrimitive<T>`
81     // - `From<T>`
82     // - `TryFromPrimitive<T>`
83     // - `TryFrom<T>`
84     let from_primitive = Enum::from_primitive(0_u8);
85     assert_eq!(from_primitive, Enum::Whatever);
86 
87     let from = Enum::from(0_u8);
88     assert_eq!(from, Enum::Whatever);
89 
90     let from_primitive = Enum::from_primitive(1_u8);
91     assert_eq!(from_primitive, Enum::Whatever);
92 
93     let from = Enum::from(1_u8);
94     assert_eq!(from, Enum::Whatever);
95 }
96 
97 #[test]
from_primitive_number_catch_all()98 fn from_primitive_number_catch_all() {
99     #[derive(Debug, Eq, PartialEq, FromPrimitive)]
100     #[repr(u8)]
101     enum Enum {
102         Zero = 0,
103         #[num_enum(catch_all)]
104         NonZero(u8),
105     }
106 
107     let zero = Enum::from_primitive(0_u8);
108     assert_eq!(zero, Enum::Zero);
109 
110     let one = Enum::from_primitive(1_u8);
111     assert_eq!(one, Enum::NonZero(1_u8));
112 
113     let two = Enum::from_primitive(2_u8);
114     assert_eq!(two, Enum::NonZero(2_u8));
115 }
116 
117 #[test]
from_primitive_number_catch_all_in_middle()118 fn from_primitive_number_catch_all_in_middle() {
119     #[derive(Debug, PartialEq, Eq, FromPrimitive)]
120     #[repr(u8)]
121     enum Enum {
122         Zero = 0,
123         #[num_enum(catch_all)]
124         Else(u8) = 2,
125         One = 1,
126     }
127 
128     let zero = Enum::from_primitive(0_u8);
129     assert_eq!(zero, Enum::Zero);
130 
131     let one = Enum::from_primitive(1_u8);
132     assert_eq!(one, Enum::One);
133 
134     let two = Enum::from_primitive(2_u8);
135     assert_eq!(two, Enum::Else(2_u8));
136 
137     let three = Enum::from_primitive(3_u8);
138     assert_eq!(three, Enum::Else(3_u8));
139 }
140 
141 #[cfg(feature = "complex-expressions")]
142 #[test]
from_primitive_number_with_inclusive_range()143 fn from_primitive_number_with_inclusive_range() {
144     #[derive(Debug, Eq, PartialEq, FromPrimitive)]
145     #[repr(u8)]
146     enum Enum {
147         Zero = 0,
148         #[num_enum(alternatives = [2..=255])]
149         NonZero,
150     }
151 
152     let zero = Enum::from_primitive(0_u8);
153     assert_eq!(zero, Enum::Zero);
154 
155     let one = Enum::from_primitive(1_u8);
156     assert_eq!(one, Enum::NonZero);
157 
158     let two = Enum::from_primitive(2_u8);
159     assert_eq!(two, Enum::NonZero);
160 
161     let three = Enum::from_primitive(3_u8);
162     assert_eq!(three, Enum::NonZero);
163 
164     let twofivefive = Enum::from_primitive(255_u8);
165     assert_eq!(twofivefive, Enum::NonZero);
166 }
167