scnr/
span.rs

1use serde::{Deserialize, Serialize};
2
3/// A span in an input string.
4#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq, Serialize, Deserialize)]
5pub struct Span {
6    /// The start offset of the span, inclusive.
7    pub start: usize,
8    /// The end offset of the span, exclusive.
9    pub end: usize,
10}
11impl Span {
12    /// Create a new span.
13    #[inline]
14    pub fn new(start: usize, end: usize) -> Self {
15        Span { start, end }
16    }
17
18    /// Check if the span is empty.
19    #[inline]
20    pub fn is_empty(&self) -> bool {
21        self.start >= self.end
22    }
23
24    /// Get the length of the span.
25    #[inline]
26    pub fn len(&self) -> usize {
27        self.end.saturating_sub(self.start)
28    }
29
30    /// Get the span as range.
31    #[inline]
32    pub fn range(self) -> std::ops::Range<usize> {
33        self.start..self.end
34    }
35}
36
37impl<T> From<std::ops::Range<T>> for Span
38where
39    T: Into<usize>,
40{
41    fn from(range: std::ops::Range<T>) -> Self {
42        Span {
43            start: range.start.into(),
44            end: range.end.into(),
45        }
46    }
47}
48
49impl<T> From<std::ops::RangeInclusive<T>> for Span
50where
51    T: Into<usize> + Copy,
52{
53    fn from(range: std::ops::RangeInclusive<T>) -> Self {
54        Span {
55            start: (*range.start()).into(),
56            end: (*range.end()).into() + 1,
57        }
58    }
59}
60
61impl<T> From<Span> for std::ops::Range<T>
62where
63    T: From<usize>,
64{
65    fn from(span: Span) -> Self {
66        span.start.into()..span.end.into()
67    }
68}
69
70impl<T> From<Span> for std::ops::RangeInclusive<T>
71where
72    T: From<usize> + Copy,
73{
74    fn from(span: Span) -> Self {
75        span.start.into()..=span.end.into()
76    }
77}
78
79impl std::fmt::Display for Span {
80    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
81        write!(f, "{}..{}", self.start, self.end)
82    }
83}