macro_rules! range_set { () => { ... }; ( ; $len:expr ) => { ... }; ( $( $num:tt ),+ ) => { ... }; ( $( $num:tt ),+ ; $len:expr ) => { ... }; ( $( $start:tt $( ..= $end:tt )? $( as $range_keyword:tt )? ),+ ) => { ... }; ( $( $start:tt $( ..= $end:tt )? $( as $range_keyword:tt )? ),+ ; $len:expr ) => { ... }; }
Expand description
Convenient macro to construct RangeSets without needing bulky notation like
::<[RangeInclusive<_>; _]>
. The macro allows a mix of numbers and
inclusive ranges, with an optional length at the end for the smallvec array
size. If the length is not specified, it will default to 4.
The implementation guarantees O(n)
construction time for lists of
non-adjacent mix of increasing-ranges and numbers in increasing order. See
RangeSet::from_ranges
for more information about this
optimization. Single numbers are transformed into one-element inclusive
ranges (5
becomes 5..=5
).
Separately, the implementation guarantees O(n)
construction time for lists
of numbers (not ranges) sorted in increasing order and deduplicated. See
[RangeSet::from_elements
] for more information about this optimization.
All other cases are reasonably performant, O(n * log(n))
on average.
let case1 = RangeSet::<[RangeInclusive<u32>; 3]>::from_valid_ranges ([0..=0, 2..=5]).unwrap();
let case2 = RangeSet::<[RangeInclusive<u32>; 4]>::from_valid_ranges ([1..=3, 6..=15, 40..=40, 42..=50]).unwrap();
const FIVE: u32 = 5;
let some_func = |x: u32| x;
let your_var = 0;
// The fastest format to use is non-adjacent, increasing ranges in increasing order.
assert_eq!(range_set![0, 2..=5; 3], case1);
assert_eq!(range_set![1..=3, 6..=15, 40, 42..=50; 4], case2);
// The smallvec size is optional, and defaults to 4.
assert_eq!(range_set![1..=3, 6..=15, 40, 42..=50], case2);
// A wide variety of other formats are available. Complex epressions need to be surrounded
// by parentheses.
assert_eq!(range_set![0, 2, 3..=5; 3], case1);
assert_eq!(range_set![0, 2, (1 + 2), 4, FIVE; 3], case1);
assert_eq!(range_set![0, 2, (some_func(3)), 4, 5; 3], case1);
assert_eq!(range_set![your_var, 2..=(some_func(5)); 3], case1);
// Expressions that return ranges need to be marked using "as range":
let my_range = 2..=5;
assert_eq!(range_set![0, my_range as range; 3], case1);
// Empty lists are still allowed. Rust may have trouble inferring the number type/size
// in some situations.
assert_eq!(range_set![], RangeSet::<[RangeInclusive<u32>; 4]>::new());
assert_eq!(range_set![; 3], RangeSet::<[RangeInclusive<u32>; 3]>::new());