1use std::ops::{Add, Deref, Range};
2
3pub trait ToSpan {
5 fn span(&self) -> Span;
7}
8
9#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
12pub struct Span(Range<usize>);
13
14impl Span {
15 pub fn new(start: usize, end: usize) -> Span {
17 Span(Range { start, end })
18 }
19
20 pub fn extend(&self, right: &Span) -> Span {
29 if self.is_empty() {
30 right.clone()
31 } else if right.is_empty() {
32 self.clone()
33 } else {
34 Span::new(self.start, right.end)
35 }
36 }
37
38 pub fn extend_to(&self, right: Span) -> Span {
40 if self.is_empty() {
41 right
42 } else if right.is_empty() {
43 self.clone()
44 } else {
45 Span::new(self.start, right.end)
46 }
47 }
48
49 }
64
65impl Deref for Span {
66 type Target = Range<usize>;
67
68 fn deref(&self) -> &Self::Target {
69 &self.0
70 }
71}
72
73impl Add for Span {
74 type Output = Self;
75
76 fn add(self, rhs: Self) -> Self::Output {
78 if self.is_empty() {
79 rhs
80 } else if rhs.is_empty() {
81 self
82 } else {
83 Span::new(
85 std::cmp::min(self.start, rhs.start),
86 std::cmp::max(self.end, rhs.end),
87 )
88 }
89 }
90}
91
92impl From<Span> for Range<usize> {
93 fn from(val: Span) -> Range<usize> {
94 val.0
95 }
96}
97
98impl From<&Span> for Range<usize> {
99 fn from(val: &Span) -> Range<usize> {
100 val.0.clone()
101 }
102}
103
104impl From<Range<usize>> for Span {
105 fn from(val: Range<usize>) -> Span {
106 Span(val)
107 }
108}
109
110impl From<&Range<usize>> for Span {
111 fn from(val: &Range<usize>) -> Span {
112 Span(val.clone())
113 }
114}
115
116#[cfg(test)]
117mod tests {
118 use super::*;
119 use std::ops::Range;
120
121 #[test]
122 fn test_extend() {
123 let rng1 = Span::new(0, 5);
124 let rng2 = Span::new(12, 15);
125 let extended_rng = Span::new(0, 15);
126 assert_eq!(extended_rng, rng1.extend_to(rng2));
127 let empty_rng = Span::default();
128 assert!(empty_rng.is_empty());
129 assert_eq!(empty_rng, empty_rng.extend(&empty_rng));
130 assert_eq!(rng1, empty_rng.extend(&rng1));
131 assert_eq!(rng1, rng1.extend(&empty_rng));
132 }
133
134 #[test]
135 fn test_add() {
136 assert_eq!(Span::new(0, 15), Span::new(0, 5) + Span::new(12, 15));
138 assert_eq!(Span::new(0, 15), Span::new(12, 15) + Span::new(0, 5));
139
140 assert_eq!(Span::new(0, 7), Span::new(0, 5) + Span::new(3, 7));
142 assert_eq!(Span::new(0, 7), Span::new(3, 7) + Span::new(0, 5));
143
144 assert_eq!(Span::new(0, 7), Span::new(0, 5) + Span::new(4, 7));
146 assert_eq!(Span::new(0, 7), Span::new(4, 7) + Span::new(0, 5));
147
148 assert_eq!(Span::new(0, 7), Span::new(0, 5) + Span::new(5, 7));
150 assert_eq!(Span::new(0, 7), Span::new(5, 7) + Span::new(0, 5));
151
152 assert_eq!(Span::default(), Span::default() + Span::default());
154 assert_eq!(Span::new(0, 5), Span::default() + Span::new(0, 5));
155 assert_eq!(Span::new(0, 5), Span::new(0, 5) + Span::default());
156 }
157
158 #[test]
159 fn test_conversions() {
160 let span: Span = Range { start: 1, end: 2 }.into();
161 assert_eq!(Span::new(1, 2), span);
162 let span: Span = (&Range { start: 2, end: 3 }).into();
163 assert_eq!(Span::new(2, 3), span);
164
165 let range: Range<usize> = Span::new(1, 2).into();
166 assert_eq!(Range { start: 1, end: 2 }, range);
167 let range: Range<usize> = (&Span::new(2, 3)).into();
168 assert_eq!(Range { start: 2, end: 3 }, range);
169 }
170
171 #[test]
172 fn test_string_application() {
173 let s = "Löwe 老虎 Léopard";
174 assert_eq!(21, s.len());
181 assert_eq!(15, s.chars().count());
185 assert_eq!("老", &s[6..9]);
189 assert_eq!("虎", &s[9..12]);
190 assert_eq!("L", &s[13..14]);
191
192 assert_eq!("老", &s[Range { start: 6, end: 9 }]);
193 assert_eq!("虎", &s[Into::<Range<usize>>::into(Span::new(9, 12))]);
194 assert_eq!("L", &s[Into::<Range<usize>>::into(Span::new(13, 14))]);
195 }
196}