1#[cfg(feature = "serialization")]
2use serde::{Deserialize, Serialize};
3use std::fmt;
4use std::ops::Range;
5
6use crate::{ByteIndex, RawIndex};
7
8#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
9#[cfg_attr(feature = "serialization", derive(Deserialize, Serialize))]
10pub struct Span {
11 start: ByteIndex,
12 end: ByteIndex,
13}
14
15impl Span {
16 pub fn new(start: impl Into<ByteIndex>, end: impl Into<ByteIndex>) -> Span {
18 let start = start.into();
19 let end = end.into();
20
21 assert!(end >= start);
22
23 Span { start, end }
24 }
25
26 pub const fn initial() -> Span {
28 Span {
29 start: ByteIndex(0),
30 end: ByteIndex(0),
31 }
32 }
33
34 pub fn from_str(s: &str) -> Span {
44 Span::new(0, s.len() as u32)
45 }
46
47 pub fn merge(self, other: Span) -> Span {
63 use std::cmp::{max, min};
64
65 let start = min(self.start, other.start);
66 let end = max(self.end, other.end);
67 Span::new(start, end)
68 }
69
70 pub fn disjoint(self, other: Span) -> bool {
79 let (first, last) = if self.end < other.end {
80 (self, other)
81 } else {
82 (other, self)
83 };
84 first.end <= last.start
85 }
86
87 pub fn start(self) -> ByteIndex {
97 self.start
98 }
99
100 pub fn end(self) -> ByteIndex {
110 self.end
111 }
112}
113
114impl Default for Span {
115 fn default() -> Span {
116 Span::initial()
117 }
118}
119
120impl fmt::Display for Span {
121 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
122 write!(
123 f,
124 "[{start}, {end})",
125 start = self.start(),
126 end = self.end(),
127 )
128 }
129}
130
131impl<I> From<Range<I>> for Span
132where
133 I: Into<ByteIndex>,
134{
135 fn from(range: Range<I>) -> Span {
136 Span::new(range.start, range.end)
137 }
138}
139
140impl From<Span> for Range<usize> {
141 fn from(span: Span) -> Range<usize> {
142 span.start.into()..span.end.into()
143 }
144}
145
146impl From<Span> for Range<RawIndex> {
147 fn from(span: Span) -> Range<RawIndex> {
148 span.start.0..span.end.0
149 }
150}
151
152#[cfg(test)]
153mod test {
154 #[test]
155 fn test_merge() {
156 use super::Span;
157
158 let a = Span::from(1..5);
160 let b = Span::from(3..10);
161 assert_eq!(a.merge(b), Span::from(1..10));
162 assert_eq!(b.merge(a), Span::from(1..10));
163
164 let two_four = (2..4).into();
166 assert_eq!(a.merge(two_four), (1..5).into());
167 assert_eq!(two_four.merge(a), (1..5).into());
168
169 let ten_twenty = (10..20).into();
171 assert_eq!(a.merge(ten_twenty), (1..20).into());
172 assert_eq!(ten_twenty.merge(a), (1..20).into());
173
174 assert_eq!(a.merge(a), a);
176 }
177
178 #[test]
179 fn test_disjoint() {
180 use super::Span;
181
182 let a = Span::from(1..5);
184 let b = Span::from(3..10);
185 assert!(!a.disjoint(b));
186 assert!(!b.disjoint(a));
187
188 let two_four = (2..4).into();
190 assert!(!a.disjoint(two_four));
191 assert!(!two_four.disjoint(a));
192
193 let ten_twenty = (10..20).into();
195 assert!(a.disjoint(ten_twenty));
196 assert!(ten_twenty.disjoint(a));
197
198 assert!(!a.disjoint(a));
200
201 let c = Span::from(5..10);
203 assert!(a.disjoint(c));
204 assert!(c.disjoint(a));
205 let d = Span::from(0..1);
207 assert!(a.disjoint(d));
208 assert!(d.disjoint(a));
209 }
210}