1#[cfg(feature = "serde")]
2use serde::Serialize;
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
6#[cfg_attr(feature = "serde", derive(Serialize))]
7pub struct Span {
8 pub start: u32,
10 pub end: u32,
12}
13
14impl Span {
15 pub const DUMMY: Span = Span { start: 0, end: 0 };
17
18 pub fn new(start: u32, end: u32) -> Self {
20 Self { start, end }
21 }
22
23 pub fn merge(self, other: Span) -> Span {
25 Span {
26 start: self.start.min(other.start),
27 end: self.end.max(other.end),
28 }
29 }
30
31 pub fn len(self) -> u32 {
33 self.end - self.start
34 }
35
36 pub fn is_empty(self) -> bool {
38 self.start == self.end
39 }
40}
41
42impl Default for Span {
43 fn default() -> Self {
44 Self::DUMMY
45 }
46}
47
48#[cfg(test)]
49mod tests {
50 use super::*;
51
52 #[test]
53 fn test_span_new() {
54 let span = Span::new(5, 10);
55 assert_eq!(span.start, 5);
56 assert_eq!(span.end, 10);
57 }
58
59 #[test]
60 fn test_span_merge() {
61 let a = Span::new(5, 10);
62 let b = Span::new(8, 15);
63 let merged = a.merge(b);
64 assert_eq!(merged.start, 5);
65 assert_eq!(merged.end, 15);
66 }
67
68 #[test]
69 fn test_span_merge_non_overlapping() {
70 let a = Span::new(0, 5);
71 let b = Span::new(10, 20);
72 let merged = a.merge(b);
73 assert_eq!(merged.start, 0);
74 assert_eq!(merged.end, 20);
75 }
76
77 #[test]
78 fn test_span_len() {
79 let span = Span::new(3, 10);
80 assert_eq!(span.len(), 7);
81 }
82
83 #[test]
84 fn test_span_is_empty() {
85 assert!(Span::new(5, 5).is_empty());
86 assert!(!Span::new(5, 6).is_empty());
87 }
88
89 #[test]
90 fn test_span_dummy() {
91 assert_eq!(Span::DUMMY, Span::new(0, 0));
92 assert!(Span::DUMMY.is_empty());
93 }
94
95 #[test]
96 fn test_span_default() {
97 assert_eq!(Span::default(), Span::DUMMY);
98 }
99}