cooklang/
span.rs

1//! Utility to represent a location in the source code
2
3use std::ops::Range;
4
5/// Location in the source code
6///
7/// The offsets are zero-indexed charactere offsets from the beginning of the source
8/// code.
9#[derive(Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize, PartialOrd, Ord)]
10pub struct Span {
11    start: usize,
12    end: usize,
13}
14
15impl Span {
16    pub(crate) fn new(start: usize, end: usize) -> Self {
17        Self { start, end }
18    }
19
20    pub(crate) fn pos(pos: usize) -> Self {
21        Self {
22            start: pos,
23            end: pos,
24        }
25    }
26
27    /// Start offset of the span
28    pub fn start(&self) -> usize {
29        self.start
30    }
31
32    /// End (exclusive) offset of the span
33    pub fn end(&self) -> usize {
34        self.end
35    }
36
37    /// Get the span as a range
38    pub fn range(&self) -> Range<usize> {
39        self.start..self.end
40    }
41
42    /// Len of the span in bytes
43    pub fn len(&self) -> usize {
44        self.end - self.start
45    }
46
47    /// Check if the span is empty
48    pub fn is_empty(&self) -> bool {
49        self.start == self.end
50    }
51}
52
53impl std::fmt::Debug for Span {
54    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55        write!(f, "{}..{}", self.start, self.end)
56    }
57}
58
59impl From<Range<usize>> for Span {
60    fn from(value: Range<usize>) -> Self {
61        Self::new(value.start, value.end)
62    }
63}
64
65impl From<Span> for Range<usize> {
66    fn from(value: Span) -> Self {
67        value.start..value.end
68    }
69}
70
71impl<T> From<crate::located::Located<T>> for Span {
72    fn from(value: crate::located::Located<T>) -> Self {
73        value.span()
74    }
75}
76
77impl crate::error::Recover for Span {
78    fn recover() -> Self {
79        Self::new(0, 0)
80    }
81}