solscript_ast/
span.rs

1//! Source location tracking for AST nodes
2
3use serde::{Deserialize, Serialize};
4
5/// A span representing a range in the source code
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
7pub struct Span {
8    /// Start byte offset (inclusive)
9    pub start: usize,
10    /// End byte offset (exclusive)
11    pub end: usize,
12}
13
14impl Span {
15    /// Create a new span
16    pub fn new(start: usize, end: usize) -> Self {
17        Self { start, end }
18    }
19
20    /// Create a dummy span for generated code
21    pub fn dummy() -> Self {
22        Self { start: 0, end: 0 }
23    }
24
25    /// Merge two spans into one that covers both
26    pub fn merge(self, other: Span) -> Span {
27        Span {
28            start: self.start.min(other.start),
29            end: self.end.max(other.end),
30        }
31    }
32
33    /// Get the length of this span
34    pub fn len(&self) -> usize {
35        self.end - self.start
36    }
37
38    /// Check if this span is empty
39    pub fn is_empty(&self) -> bool {
40        self.start == self.end
41    }
42
43    /// Check if this is a dummy span
44    pub fn is_dummy(&self) -> bool {
45        self.start == 0 && self.end == 0
46    }
47}
48
49/// A value with an associated span
50#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
51pub struct Spanned<T> {
52    pub value: T,
53    pub span: Span,
54}
55
56impl<T> Spanned<T> {
57    pub fn new(value: T, span: Span) -> Self {
58        Self { value, span }
59    }
60
61    pub fn map<U>(self, f: impl FnOnce(T) -> U) -> Spanned<U> {
62        Spanned {
63            value: f(self.value),
64            span: self.span,
65        }
66    }
67}
68
69impl<T> std::ops::Deref for Spanned<T> {
70    type Target = T;
71
72    fn deref(&self) -> &Self::Target {
73        &self.value
74    }
75}