Skip to main content

shannon_brush_parser/
source.rs

1use std::{fmt::Display, sync::Arc};
2
3/// Represents a position in source text.
4#[derive(Clone, Default, Debug)]
5#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
6#[cfg_attr(
7    any(test, feature = "serde"),
8    derive(PartialEq, Eq, serde::Serialize, serde::Deserialize)
9)]
10pub struct SourcePosition {
11    /// The 0-based index of the character in the input stream.
12    pub index: usize,
13    /// The 1-based line number.
14    pub line: usize,
15    /// The 1-based column number.
16    pub column: usize,
17}
18
19impl Display for SourcePosition {
20    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
21        f.write_fmt(format_args!("{},{}", self.line, self.column))
22    }
23}
24
25impl SourcePosition {
26    /// Returns a new `SourcePosition` offset by the given `SourcePositionOffset`.
27    ///
28    /// # Arguments
29    ///
30    /// * `offset` - The offset to apply.
31    #[must_use]
32    pub const fn offset(&self, offset: &SourcePositionOffset) -> Self {
33        Self {
34            index: self.index + offset.index,
35            line: self.line + offset.line,
36            column: if offset.line == 0 {
37                self.column + offset.column
38            } else {
39                offset.column + 1
40            },
41        }
42    }
43}
44
45#[cfg(feature = "diagnostics")]
46impl From<&SourcePosition> for miette::SourceOffset {
47    #[allow(clippy::cast_sign_loss)]
48    fn from(position: &SourcePosition) -> Self {
49        position.index.into()
50    }
51}
52
53/// Represents an offset in source text.
54#[derive(Clone, Default, Debug)]
55#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
56#[cfg_attr(
57    any(test, feature = "serde"),
58    derive(PartialEq, Eq, serde::Serialize, serde::Deserialize)
59)]
60pub struct SourcePositionOffset {
61    /// The 0-based character offset.
62    pub index: usize,
63    /// The 0-based line offset.
64    pub line: usize,
65    /// The 0-based column offset.
66    pub column: usize,
67}
68
69/// Represents a span within source text.
70#[derive(Clone, Default, Debug)]
71#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
72#[cfg_attr(
73    any(test, feature = "serde"),
74    derive(PartialEq, Eq, serde::Serialize, serde::Deserialize)
75)]
76pub struct SourceSpan {
77    /// The start position.
78    pub start: Arc<SourcePosition>,
79    /// The end position of the span (exclusive).
80    pub end: Arc<SourcePosition>,
81}
82
83impl SourceSpan {
84    /// Returns the length of the token in characters.
85    pub fn length(&self) -> usize {
86        self.end.index - self.start.index
87    }
88    pub(crate) fn within(start: &Self, end: &Self) -> Self {
89        Self {
90            start: start.start.clone(),
91            end: end.end.clone(),
92        }
93    }
94}