From d5a4caa43908afc92dd88b89badc58f72752fdc7 Mon Sep 17 00:00:00 2001 From: Mark Giraud Date: Thu, 16 Feb 2023 22:37:44 +0100 Subject: [PATCH] fix(#102): Fixed shift error on >64 bit enums (#103) Large enums realistically will never be naturally exhaustive due to their size. The shift is now done as a checked shift and when the shift fails it will default to not naturally exhaustive, requiring the default attribute, even if it were exhaustive. (I want to meet the person who manages to write down 2^64 enum values or more) --- num_enum/tests/from_primitive.rs | 20 ++++++++++++++++++++ num_enum_derive/src/lib.rs | 5 +++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/num_enum/tests/from_primitive.rs b/num_enum/tests/from_primitive.rs index 2c72c6c..d727db2 100644 --- a/num_enum/tests/from_primitive.rs +++ b/num_enum/tests/from_primitive.rs @@ -8,6 +8,26 @@ mod core {} mod num_enum {} mod std {} +#[test] +fn has_from_primitive_number_u64() { + #[derive(Debug, Eq, PartialEq, FromPrimitive)] + #[repr(u64)] + enum Enum { + Zero = 0, + #[num_enum(default)] + NonZero = 1, + } + + let zero = Enum::from_primitive(0_u64); + assert_eq!(zero, Enum::Zero); + + let one = Enum::from_primitive(1_u64); + assert_eq!(one, Enum::NonZero); + + let two = Enum::from_primitive(2_u64); + assert_eq!(two, Enum::NonZero); +} + #[test] fn has_from_primitive_number() { #[derive(Debug, Eq, PartialEq, FromPrimitive)] diff --git a/num_enum_derive/src/lib.rs b/num_enum_derive/src/lib.rs index 8c77862..a7f8843 100644 --- a/num_enum_derive/src/lib.rs +++ b/num_enum_derive/src/lib.rs @@ -209,8 +209,9 @@ impl EnumInfo { .strip_prefix('i') .or_else(|| repr_str.strip_prefix('u')); if let Some(suffix) = suffix { - if let Ok(bits) = suffix.parse::() { - return Ok(1 << bits == self.variants.len()); + if let Ok(bits) = suffix.parse::() { + let variants = 1usize.checked_shl(bits); + return Ok(variants.map_or(false, |v| v == self.variants.len())); } } }