1use core::cmp;
2use core::fmt;
3use core::ops;
4
5use serde::{Deserialize, Serialize};
6
7use crate::ast::prelude::*;
8
9#[derive(Default, TryClone, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
11#[try_clone(copy)]
12pub struct Span {
13 pub start: ByteIndex,
15 pub end: ByteIndex,
17}
18
19impl Span {
20 pub fn new<S, E>(start: S, end: E) -> Self
31 where
32 S: TryInto<ByteIndex>,
33 S::Error: fmt::Debug,
34 E: TryInto<ByteIndex>,
35 E::Error: fmt::Debug,
36 {
37 Self {
38 start: start.try_into().expect("start out of bounds"),
39 end: end.try_into().expect("end out of bounds"),
40 }
41 }
42
43 pub fn point<P>(pos: P) -> Self
54 where
55 P: TryInto<ByteIndex>,
56 P::Error: fmt::Debug,
57 {
58 let pos = pos.try_into().expect("point out of bounds");
59
60 Self {
61 start: pos,
62 end: pos,
63 }
64 }
65
66 pub const fn empty() -> Self {
76 Self {
77 start: ByteIndex(0),
78 end: ByteIndex(0),
79 }
80 }
81
82 pub fn head(self) -> Self {
84 Self {
85 start: self.start,
86 end: self.start,
87 }
88 }
89
90 pub fn tail(self) -> Self {
92 Self {
93 start: self.end,
94 end: self.end,
95 }
96 }
97
98 pub fn join(self, other: Self) -> Self {
111 Self {
112 start: ByteIndex::min(self.start, other.start),
113 end: ByteIndex::max(self.end, other.end),
114 }
115 }
116
117 pub fn narrow(self, amount: impl Into<ByteIndex>) -> Self {
131 let amount = amount.into();
132 let end = ByteIndex::max(self.start, self.end.saturating_sub(amount));
133 let start = ByteIndex::min(self.start.saturating_add(amount), end);
134 Self { start, end }
135 }
136
137 pub fn range(self) -> ops::Range<usize> {
144 ops::Range {
145 start: usize::try_from(self.start.0).expect("start index out of bounds"),
146 end: usize::try_from(self.end.0).expect("end index out of bounds"),
147 }
148 }
149
150 pub(crate) fn trim_start(self, amount: impl Into<ByteIndex>) -> Self {
152 let amount = amount.into();
153
154 Self {
155 start: ByteIndex::min(self.start.saturating_add(amount), self.end),
156 end: self.end,
157 }
158 }
159
160 pub(crate) fn trim_end(self, amount: impl Into<ByteIndex>) -> Self {
162 let amount = amount.into();
163
164 Self {
165 start: self.start,
166 end: ByteIndex::max(self.end.saturating_sub(amount), self.start),
167 }
168 }
169}
170
171impl Serialize for Span {
172 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
173 where
174 S: serde::Serializer,
175 {
176 (self.start, self.end).serialize(serializer)
177 }
178}
179
180impl<'de> Deserialize<'de> for Span {
181 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
182 where
183 D: serde::Deserializer<'de>,
184 {
185 let (start, end) = <(ByteIndex, ByteIndex)>::deserialize(deserializer)?;
186 Ok(Self { start, end })
187 }
188}
189
190impl fmt::Display for Span {
191 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
192 write!(fmt, "{}:{}", self.start, self.end)
193 }
194}
195
196impl fmt::Debug for Span {
197 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
198 write!(f, "{}:{}", self.start, self.end)
199 }
200}
201
202#[derive(
204 Default, TryClone, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize,
205)]
206#[repr(transparent)]
207#[serde(transparent)]
208#[try_clone(copy)]
209pub struct ByteIndex(#[doc(hidden)] pub u32);
210
211impl ByteIndex {
212 pub fn into_usize(self) -> usize {
219 usize::try_from(self.0).expect("byte index out of range")
220 }
221
222 fn min(a: Self, b: Self) -> Self {
223 Self(u32::min(a.0, b.0))
224 }
225
226 fn max(a: Self, b: Self) -> Self {
227 Self(u32::max(a.0, b.0))
228 }
229
230 pub(crate) fn saturating_sub(self, other: Self) -> Self {
231 Self(self.0.saturating_sub(other.0))
232 }
233
234 fn saturating_add(self, other: Self) -> Self {
235 Self(self.0.saturating_add(other.0))
236 }
237}
238
239impl From<u32> for ByteIndex {
240 fn from(value: u32) -> Self {
241 Self(value)
242 }
243}
244
245impl TryFrom<usize> for ByteIndex {
246 type Error = <usize as TryFrom<u32>>::Error;
247
248 fn try_from(value: usize) -> Result<Self, Self::Error> {
249 Ok(Self(u32::try_from(value)?))
250 }
251}
252
253impl TryFrom<i32> for ByteIndex {
254 type Error = <i32 as TryFrom<u32>>::Error;
255
256 fn try_from(value: i32) -> Result<Self, Self::Error> {
257 Ok(Self(u32::try_from(value)?))
258 }
259}
260
261impl fmt::Display for ByteIndex {
262 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
263 write!(f, "{}", self.0)
264 }
265}
266
267impl fmt::Debug for ByteIndex {
268 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
269 write!(f, "{}", self.0)
270 }
271}
272
273impl cmp::PartialEq<usize> for ByteIndex {
274 fn eq(&self, other: &usize) -> bool {
275 match u32::try_from(*other) {
276 Ok(other) => self.0 == other,
277 Err(..) => false,
278 }
279 }
280}
281
282impl cmp::PartialEq<u32> for ByteIndex {
283 fn eq(&self, other: &u32) -> bool {
284 self.0 == *other
285 }
286}