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