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