Skip to main content

oxide_sql_core/lexer/
span.rs

1//! Source location tracking for tokens and AST nodes.
2
3/// Represents a span in the source code.
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5pub struct Span {
6    /// Start byte offset (inclusive).
7    pub start: usize,
8    /// End byte offset (exclusive).
9    pub end: usize,
10}
11
12impl Span {
13    /// Creates a new span.
14    #[must_use]
15    pub const fn new(start: usize, end: usize) -> Self {
16        Self { start, end }
17    }
18
19    /// Returns the length of the span in bytes.
20    #[must_use]
21    pub const fn len(&self) -> usize {
22        self.end - self.start
23    }
24
25    /// Returns true if the span is empty.
26    #[must_use]
27    pub const fn is_empty(&self) -> bool {
28        self.start == self.end
29    }
30
31    /// Merges two spans into one that covers both.
32    #[must_use]
33    pub const fn merge(self, other: Self) -> Self {
34        let start = if self.start < other.start {
35            self.start
36        } else {
37            other.start
38        };
39        let end = if self.end > other.end {
40            self.end
41        } else {
42            other.end
43        };
44        Self { start, end }
45    }
46}
47
48impl Default for Span {
49    fn default() -> Self {
50        Self::new(0, 0)
51    }
52}
53
54#[cfg(test)]
55mod tests {
56    use super::*;
57
58    #[test]
59    fn test_span_new() {
60        let span = Span::new(5, 10);
61        assert_eq!(span.start, 5);
62        assert_eq!(span.end, 10);
63    }
64
65    #[test]
66    fn test_span_len() {
67        let span = Span::new(5, 10);
68        assert_eq!(span.len(), 5);
69    }
70
71    #[test]
72    fn test_span_is_empty() {
73        let empty = Span::new(5, 5);
74        let non_empty = Span::new(5, 10);
75        assert!(empty.is_empty());
76        assert!(!non_empty.is_empty());
77    }
78
79    #[test]
80    fn test_span_merge() {
81        let span1 = Span::new(5, 10);
82        let span2 = Span::new(8, 15);
83        let merged = span1.merge(span2);
84        assert_eq!(merged.start, 5);
85        assert_eq!(merged.end, 15);
86    }
87}