surrealguard_syntax/
span.rs1use serde::{Deserialize, Serialize};
4
5use crate::source::SourceId;
6
7#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
9pub struct ByteRange {
10 start: u32,
11 end: u32,
12}
13
14impl ByteRange {
15 pub fn new(start: u32, end: u32) -> Result<Self, InvalidByteRange> {
17 if start <= end {
18 Ok(Self { start, end })
19 } else {
20 Err(InvalidByteRange { start, end })
21 }
22 }
23
24 pub fn start(self) -> u32 {
26 self.start
27 }
28
29 pub fn end(self) -> u32 {
31 self.end
32 }
33
34 pub fn len(self) -> u32 {
36 self.end - self.start
37 }
38
39 pub fn is_empty(self) -> bool {
41 self.start == self.end
42 }
43}
44
45#[derive(Clone, Copy, Debug, PartialEq, Eq)]
47pub struct InvalidByteRange {
48 start: u32,
49 end: u32,
50}
51
52impl InvalidByteRange {
53 pub fn start(self) -> u32 {
55 self.start
56 }
57
58 pub fn end(self) -> u32 {
60 self.end
61 }
62}
63
64#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
66pub struct SourceSpan {
67 source: SourceId,
68 range: ByteRange,
69}
70
71impl SourceSpan {
72 pub fn new(source: SourceId, range: ByteRange) -> Self {
74 Self { source, range }
75 }
76
77 pub fn source(&self) -> &SourceId {
79 &self.source
80 }
81
82 pub fn range(&self) -> ByteRange {
84 self.range
85 }
86}
87
88#[cfg(test)]
89mod tests {
90 use super::*;
91 use crate::source::SourceId;
92
93 #[test]
94 fn byte_range_accepts_ordered_bounds() {
95 let range = ByteRange::new(0, 3).expect("ordered range should be valid");
96
97 assert_eq!(range.start(), 0);
98 assert_eq!(range.end(), 3);
99 assert_eq!(range.len(), 3);
100 assert!(!range.is_empty());
101 }
102
103 #[test]
104 fn byte_range_rejects_reversed_bounds() {
105 let error = ByteRange::new(3, 0).expect_err("reversed range should be invalid");
106
107 assert_eq!(error.start(), 3);
108 assert_eq!(error.end(), 0);
109 }
110
111 #[test]
112 fn source_span_preserves_source_identity_and_range() {
113 let source = SourceId::new("query:001");
114 let range = ByteRange::new(4, 9).expect("range should be valid");
115
116 let span = SourceSpan::new(source.clone(), range);
117
118 assert_eq!(span.source(), &source);
119 assert_eq!(span.range(), range);
120 }
121}