1use std::fmt;
4use std::ops::Range;
5
6#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
12#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
13pub struct Span {
14 pub start: usize,
16 pub end: usize,
18}
19
20impl Span {
21 #[must_use]
27 pub const fn new(start: usize, end: usize) -> Self {
28 assert!(start <= end, "a span cannot end before it starts");
29 Self { start, end }
30 }
31
32 #[must_use]
34 pub const fn empty(offset: usize) -> Self {
35 Self::new(offset, offset)
36 }
37
38 #[must_use]
40 pub const fn start(self) -> usize {
41 self.start
42 }
43
44 #[must_use]
46 pub const fn end(self) -> usize {
47 self.end
48 }
49
50 #[must_use]
52 pub const fn len(self) -> usize {
53 self.end - self.start
54 }
55
56 #[must_use]
58 pub const fn is_empty(self) -> bool {
59 self.start == self.end
60 }
61
62 #[must_use]
64 pub const fn contains(self, offset: usize) -> bool {
65 self.start <= offset && offset < self.end
66 }
67
68 #[must_use]
70 pub const fn contains_span(self, other: Self) -> bool {
71 self.start <= other.start && other.end <= self.end
72 }
73
74 #[must_use]
76 pub const fn cover(self, other: Self) -> Self {
77 Self::new(
78 if self.start < other.start {
79 self.start
80 } else {
81 other.start
82 },
83 if self.end > other.end {
84 self.end
85 } else {
86 other.end
87 },
88 )
89 }
90
91 #[must_use]
93 pub const fn range(self) -> Range<usize> {
94 self.start..self.end
95 }
96
97 #[must_use]
102 pub fn text(self, source: &str) -> Option<&str> {
103 source.get(self.range())
104 }
105}
106
107impl From<Range<usize>> for Span {
108 fn from(range: Range<usize>) -> Self {
109 Self::new(range.start, range.end)
110 }
111}
112
113impl From<Span> for Range<usize> {
114 fn from(span: Span) -> Self {
115 span.range()
116 }
117}
118
119impl fmt::Debug for Span {
120 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
121 write!(formatter, "{}..{}", self.start, self.end)
122 }
123}
124
125impl fmt::Display for Span {
126 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
127 fmt::Debug::fmt(self, formatter)
128 }
129}