Skip to main content

ocelot_base/
span.rs

1use std::ops::Range;
2
3/// Byte span within a source buffer.
4#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
5pub struct Span(Range<usize>);
6
7impl Span {
8    /// Creates a new span from a start and end offset.
9    pub const fn new(start: usize, end: usize) -> Self {
10        Self(start..end)
11    }
12
13    /// Returns the start offset.
14    pub const fn start(&self) -> usize {
15        self.0.start
16    }
17
18    /// Returns the end offset.
19    pub const fn end(&self) -> usize {
20        self.0.end
21    }
22
23    /// Returns the underlying range.
24    pub fn as_range(&self) -> Range<usize> {
25        self.0.clone()
26    }
27
28    /// Returns the span length.
29    pub fn len(&self) -> usize {
30        self.0.len()
31    }
32
33    /// Returns whether the span is empty.
34    pub fn is_empty(&self) -> bool {
35        self.0.is_empty()
36    }
37}
38
39impl From<Range<usize>> for Span {
40    fn from(value: Range<usize>) -> Self {
41        Self(value)
42    }
43}
44
45impl From<Span> for Range<usize> {
46    fn from(value: Span) -> Self {
47        value.0
48    }
49}
50
51#[cfg(test)]
52mod tests {
53    use super::Span;
54
55    #[test]
56    fn span_exposes_offsets_and_length() {
57        let span = Span::new(2, 5);
58
59        assert_eq!(span.start(), 2);
60        assert_eq!(span.end(), 5);
61        assert_eq!(span.len(), 3);
62        assert!(!span.is_empty());
63        assert_eq!(span.as_range(), 2..5);
64    }
65
66    #[test]
67    fn empty_span_reports_empty() {
68        let span = Span::new(3, 3);
69
70        assert!(span.is_empty());
71        assert_eq!(span.len(), 0);
72    }
73}