1use std::ops::{Add, Neg, Range, RangeInclusive, Sub};
4
5#[allow(clippy::reversed_empty_ranges)] pub fn empty_range() -> RangeInclusive<isize> {
9 0 ..= -1
10}
11
12pub trait RangeExt
15where Self::Idx: Copy, Self: Sized {
16 type Idx;
17 fn mv(&self, l: Self::Idx, r: Self::Idx) -> Self;
18 fn shift(&self, a: Self::Idx) -> Self {
19 self.mv(a, a)
20 }
21}
22
23impl<Idx> RangeExt for Range<Idx>
24where Idx: Copy + Add<Output = Idx> + Sub<Output = Idx> + Neg<Output = Idx> {
25 type Idx = Idx;
26
27 fn mv(&self, l: Self::Idx, r: Self::Idx) -> Self {
28 (self.start + l) .. (self.end + r)
29 }
30}
31
32impl<Idx> RangeExt for RangeInclusive<Idx>
33where Idx: Copy + Add<Output = Idx> + Sub<Output = Idx> + Neg<Output = Idx> {
34 type Idx = Idx;
35
36 fn mv(&self, l: Self::Idx, r: Self::Idx) -> Self {
37 (*self.start() + l) ..= (*self.end() + r)
38 }
39}
40
41#[cfg(test)]
42mod tests {
43 use crate::ext::{empty_range, RangeExt};
44
45 #[test]
46 fn empty() {
47 let r = empty_range();
48 assert!(r.is_empty());
49 assert_eq!(r.clone().count(), 0);
50 assert!(!r.contains(&0));
51 }
52
53 #[test]
54 fn range() {
55 let r = -1 .. 3;
56 assert_eq!(r.mv(2, 3), 1 .. 6);
57 assert_eq!(r.shift(2), 1 .. 5);
58 }
59
60 #[test]
61 fn range_incl() {
62 let r = -1 ..= 3;
63 assert_eq!(r.mv(2, 3), 1 ..= 6);
64 assert_eq!(r.shift(2), 1 ..= 5);
65 }
66}