Skip to content

Commit

Permalink
Support specifying ranges of alternate values
Browse files Browse the repository at this point in the history
For simplicity, we require both ends of the range to be specified an
literals.

This only works if the `complex-expressions` feature is enabled, as
`syn` can't parse ranges without its `full` feature being enabled, which
significantly increases compile times. We give a useful error if you
attempt to use ranges without this feature being enabled.
  • Loading branch information
illicitonion committed Feb 20, 2023
1 parent abef42b commit 03b08be
Show file tree
Hide file tree
Showing 23 changed files with 414 additions and 101 deletions.
27 changes: 27 additions & 0 deletions num_enum/tests/from_primitive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,30 @@ fn from_primitive_number_catch_all() {
let two = Enum::from_primitive(2_u8);
assert_eq!(two, Enum::NonZero(2_u8));
}

#[cfg(feature = "complex-expressions")]
#[test]
fn from_primitive_number_with_inclusive_range() {
#[derive(Debug, Eq, PartialEq, FromPrimitive)]
#[repr(u8)]
enum Enum {
Zero = 0,
#[num_enum(alternatives = [2..=255])]
NonZero,
}

let zero = Enum::from_primitive(0_u8);
assert_eq!(zero, Enum::Zero);

let one = Enum::from_primitive(1_u8);
assert_eq!(one, Enum::NonZero);

let two = Enum::from_primitive(2_u8);
assert_eq!(two, Enum::NonZero);

let three = Enum::from_primitive(3_u8);
assert_eq!(three, Enum::NonZero);

let twofivefive = Enum::from_primitive(255_u8);
assert_eq!(twofivefive, Enum::NonZero);
}
34 changes: 31 additions & 3 deletions num_enum/tests/try_build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,42 @@ fn trybuild() {

let mut _renamer = None;

let compile_fail_dir = directory.join("compile_fail");

// Sometimes error messages change on beta/nightly - allow alternate errors on those.
_renamer = Some(Renamer::rename(directory.join("compile_fail")).unwrap());
_renamer = Some(Renamer::rename(compile_fail_dir.clone()).unwrap());

let fail = trybuild::TestCases::new();
fail.compile_fail(directory.join("compile_fail/*.rs"));
fail.compile_fail(compile_fail_dir.join("*.rs"));
add_feature_dirs(&compile_fail_dir, &fail, ExpectedResult::Fail);

let pass = trybuild::TestCases::new();
pass.pass(directory.join("pass/*.rs"));
let pass_dir = directory.join("pass");
pass.pass(pass_dir.join("*.rs"));
add_feature_dirs(&pass_dir, &pass, ExpectedResult::Pass);
}

enum ExpectedResult {
Pass,
Fail,
}

fn add_feature_dirs(
parent_dir: &Path,
test_cases: &trybuild::TestCases,
expected_result: ExpectedResult,
) {
let features_dir = parent_dir.join("features");
let feature_specific_dir = if cfg!(feature = "complex-expressions") {
features_dir.join("complex-expressions")
} else {
features_dir.join("!complex-expressions")
};
let tests = feature_specific_dir.join("*.rs");
match expected_result {
ExpectedResult::Pass => test_cases.pass(tests),
ExpectedResult::Fail => test_cases.compile_fail(tests),
}
}

struct Renamer(Vec<PathBuf>);
Expand Down
7 changes: 0 additions & 7 deletions num_enum/tests/try_build/compile_fail/exhaustive_enum.stderr

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#[derive(num_enum::FromPrimitive)]
#[repr(u8)]
enum Numbers {
Zero = 0,
#[num_enum(alternatives = [2..=255])]
NonZero = 1,
}

fn main() {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
error: Ranges are only supported as num_enum alternate values if the `complex-expressions` feature of the crate `num_enum` is enabled
--> tests/try_build/compile_fail/features/!complex-expressions/alternate_exprs_with_range.rs:5:32
|
5 | #[num_enum(alternatives = [2..=255])]
| ^^^^^^^
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#[derive(num_enum::TryFromPrimitive)]
#[repr(u8)]
enum Numbers {
Zero = 0,
#[num_enum(alternatives = [..255])]
NonZero = 1,
}

fn main() {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
error: When ranges are used for alternate values, both bounds most be explicitly specified numeric literals
--> tests/try_build/compile_fail/features/complex-expressions/alternate_exprs_range_missing_lower_bound.rs:5:32
|
5 | #[num_enum(alternatives = [..255])]
| ^^^^^
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#[derive(num_enum::TryFromPrimitive)]
#[repr(u8)]
enum Numbers {
Zero = 0,
#[num_enum(alternatives = [2..])]
NonZero = 1,
}

fn main() {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
error: When ranges are used for alternate values, both bounds most be explicitly specified numeric literals
--> tests/try_build/compile_fail/features/complex-expressions/alternate_exprs_range_missing_upper_bound.rs:5:32
|
5 | #[num_enum(alternatives = [2..])]
| ^^^
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const TWO: u8 = 2;

#[derive(num_enum::TryFromPrimitive)]
#[repr(u8)]
enum Numbers {
Zero = 0,
#[num_enum(alternatives = [TWO..=255])]
NonZero = 1,
}

fn main() {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
error: When ranges are used for alternate values, both bounds most be explicitly specified numeric literals
--> tests/try_build/compile_fail/features/complex-expressions/alternate_exprs_range_nonlit_lower_bound.rs:7:32
|
7 | #[num_enum(alternatives = [TWO..=255])]
| ^^^^^^^^^
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const TWOFIVEFIVE: u8 = 255;

#[derive(num_enum::TryFromPrimitive)]
#[repr(u8)]
enum Numbers {
Zero = 0,
#[num_enum(alternatives = [2..=TWOFIVEFIVE])]
NonZero = 1,
}

fn main() {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
error: When ranges are used for alternate values, both bounds most be explicitly specified numeric literals
--> tests/try_build/compile_fail/features/complex-expressions/alternate_exprs_range_nonlit_upper_bound.rs:7:32
|
7 | #[num_enum(alternatives = [2..=TWOFIVEFIVE])]
| ^^^^^^^^^^^^^^^
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#[derive(num_enum::TryFromPrimitive)]
#[repr(u8)]
enum Numbers {
Zero = 0,
#[num_enum(alternatives = [255..=2])]
NonZero = 1,
}

fn main() {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
error: When using ranges for alternate values, upper bound must not be less than lower bound
--> tests/try_build/compile_fail/features/complex-expressions/alternate_exprs_range_swapped_bounds.rs:5:32
|
5 | #[num_enum(alternatives = [255..=2])]
| ^^^^^^^
78 changes: 0 additions & 78 deletions num_enum/tests/try_build/pass/exhaustive_enum.rs

This file was deleted.

40 changes: 40 additions & 0 deletions num_enum/tests/try_build/pass/exhaustive_enum_try_from.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#[derive(num_enum::TryFromPrimitive)]
#[repr(u8)]
enum ExhaustiveTryFrom {
#[num_enum(alternatives = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])]
A = 0,
#[num_enum(alternatives = [17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31])]
B = 16,
#[num_enum(alternatives = [33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47])]
C = 32,
#[num_enum(alternatives = [49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63])]
D = 48,
#[num_enum(alternatives = [65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79])]
E = 64,
#[num_enum(alternatives = [81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95])]
F = 80,
#[num_enum(alternatives = [97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111])]
G = 96,
#[num_enum(alternatives = [113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127])]
H = 112,
#[num_enum(alternatives = [129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143])]
I = 128,
#[num_enum(alternatives = [145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159])]
J = 144,
#[num_enum(alternatives = [161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175])]
K = 160,
#[num_enum(alternatives = [177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191])]
L = 176,
#[num_enum(alternatives = [193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207])]
M = 192,
#[num_enum(alternatives = [209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223])]
N = 208,
#[num_enum(alternatives = [225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239])]
O = 224,
#[num_enum(alternatives = [241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255])]
P = 240,
}

fn main() {

}
39 changes: 39 additions & 0 deletions num_enum/tests/try_build/pass/exhaustive_enum_via_default.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#[derive(num_enum::FromPrimitive)]
#[repr(u8)]
enum ExhaustiveFrom {
#[num_enum(default)]
#[num_enum(alternatives = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])]
A = 0,
#[num_enum(alternatives = [17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31])]
B = 16,
#[num_enum(alternatives = [33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47])]
C = 32,
#[num_enum(alternatives = [49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63])]
D = 48,
#[num_enum(alternatives = [65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79])]
E = 64,
#[num_enum(alternatives = [81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95])]
F = 80,
#[num_enum(alternatives = [97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111])]
G = 96,
#[num_enum(alternatives = [113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127])]
H = 112,
#[num_enum(alternatives = [129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143])]
I = 128,
#[num_enum(alternatives = [145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159])]
J = 144,
#[num_enum(alternatives = [161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175])]
K = 160,
#[num_enum(alternatives = [177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191])]
L = 176,
#[num_enum(alternatives = [193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207])]
M = 192,
#[num_enum(alternatives = [209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223])]
N = 208,
#[num_enum(alternatives = [225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239])]
O = 224,
}

fn main() {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#[derive(num_enum::FromPrimitive)]
#[repr(u8)]
enum Numbers {
Zero = 0,
#[num_enum(alternatives = [2..=255])]
NonZero = 1,
}

fn main() {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#[derive(num_enum::TryFromPrimitive)]
#[repr(u8)]
enum Numbers {
Zero = 0,
#[num_enum(alternatives = [2..255])]
NonZero = 1,
}

fn main() {

}
Loading

0 comments on commit 03b08be

Please sign in to comment.