1use std::ops::Range;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
7pub struct Span {
8 pub start: usize,
9 pub end: usize,
10}
11
12impl Span {
13 pub fn new(start: usize, end: usize) -> Self {
14 Self { start, end }
15 }
16
17 pub fn dummy() -> Self {
19 Self { start: 0, end: 0 }
20 }
21
22 pub fn join(self, other: Self) -> Self {
24 Self {
25 start: self.start.min(other.start),
26 end: self.end.max(other.end),
27 }
28 }
29}
30
31impl From<Span> for Range<usize> {
32 fn from(s: Span) -> Self {
33 s.start..s.end
34 }
35}
36
37impl From<Range<usize>> for Span {
38 fn from(r: Range<usize>) -> Self {
39 Self {
40 start: r.start,
41 end: r.end,
42 }
43 }
44}
45
46#[cfg(test)]
47mod tests {
48 use super::Span;
49 use std::ops::Range;
50
51 const DEFAULT_START: usize = 0;
52 const DEFAULT_END: usize = 10;
53
54 #[test]
55 fn span_basic() {
56 let span = Span::new(DEFAULT_START, DEFAULT_END);
57 assert_eq!(span.start, DEFAULT_START);
58 assert_eq!(span.end, DEFAULT_END);
59 }
60
61 #[test]
62 fn span_dummy() {
63 let span = Span::dummy();
64 assert_eq!(span.start, DEFAULT_START);
65 assert_eq!(span.end, DEFAULT_START);
66 }
67
68 #[test]
69 fn span_join_non_overlapping() {
70 let span = Span::new(DEFAULT_START, DEFAULT_START + 3);
71 let span_other = Span::new(DEFAULT_START, DEFAULT_START + 15);
72 assert_eq!(span.join(span_other), Span::new(DEFAULT_START, DEFAULT_START + 15));
73 }
74
75 #[test]
76 fn span_join_overlapping() {
77 let span = Span::new(DEFAULT_START, DEFAULT_START + 5);
78 let span_other = Span::new(DEFAULT_START + 10, DEFAULT_START + 15);
79 assert_eq!(span.join(span_other), Span::new(DEFAULT_START, DEFAULT_START + 15));
80 }
81
82 #[test]
83 fn span_from_range() {
84 let range = DEFAULT_START..DEFAULT_END;
85 assert_eq!(Span::new(DEFAULT_START, DEFAULT_END), Span::from(range));
86 }
87
88 #[test]
89 fn range_from_span() {
90 let span = Span::new(DEFAULT_START, DEFAULT_END);
91 assert_eq!(DEFAULT_START..DEFAULT_END, Range::from(span));
92 }
93
94 #[test]
95 fn range_from_span_using_into() {
96 let span = Span::new(DEFAULT_START, DEFAULT_END);
97 let range: Range<usize> = span.into();
98 assert_eq!(range, DEFAULT_START..DEFAULT_END);
99 }
100}