Skip to main content

reading_liner/
location.rs

1use std::ops;
2
3/// Zero-based offset of bytes, only BYTES
4#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
5pub struct Offset(pub usize);
6
7impl Offset {
8    pub fn new(raw: usize) -> Self {
9        Self(raw)
10    }
11
12    pub fn raw(&self) -> usize {
13        self.0
14    }
15
16    fn plus(self, that: Self) -> Self {
17        Self(self.raw() + that.raw())
18    }
19
20    fn minus(self, that: Self) -> Self {
21        Self(self.raw() - that.raw())
22    }
23}
24
25impl From<usize> for Offset {
26    fn from(value: usize) -> Self {
27        Offset(value)
28    }
29}
30
31impl From<Offset> for usize {
32    fn from(value: Offset) -> Self {
33        value.raw()
34    }
35}
36
37impl Default for Offset {
38    fn default() -> Self {
39        Self(0)
40    }
41}
42
43impl ops::Add for Offset {
44    type Output = Offset;
45
46    fn add(self, rhs: Offset) -> Self::Output {
47        self.plus(rhs)
48    }
49}
50
51impl ops::Add<usize> for Offset {
52    type Output = Offset;
53
54    fn add(self, rhs: usize) -> Self::Output {
55        self.plus(Offset(rhs))
56    }
57}
58
59impl ops::AddAssign for Offset {
60    fn add_assign(&mut self, rhs: Self) {
61        self.0 += rhs.raw();
62    }
63}
64
65impl ops::AddAssign<usize> for Offset {
66    fn add_assign(&mut self, rhs: usize) {
67        self.0 += rhs;
68    }
69}
70
71impl ops::Sub for Offset {
72    type Output = Offset;
73
74    fn sub(self, rhs: Self) -> Self::Output {
75        self.minus(rhs)
76    }
77}
78
79impl ops::Sub<usize> for Offset {
80    type Output = Offset;
81
82    fn sub(self, rhs: usize) -> Self::Output {
83        self.minus(rhs.into())
84    }
85}
86
87/// For convenience
88pub trait OffsetRangeExt {
89    fn to_usize(self) -> ops::Range<usize>;
90}
91
92impl OffsetRangeExt for ops::Range<Offset> {
93    fn to_usize(self) -> ops::Range<usize> {
94        self.start.raw()..self.end.raw()
95    }
96}
97
98pub mod line_column {
99    use std::num::NonZeroUsize;
100
101    /// Zero-based (line, column) location
102    #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
103    pub struct ZeroBased {
104        pub line: usize,
105        pub column: usize,
106    }
107
108    impl ZeroBased {
109        pub fn new(line: usize, column: usize) -> Self {
110            Self { line, column }
111        }
112
113        pub fn raw(&self) -> (usize, usize) {
114            (self.line, self.column)
115        }
116
117        /// Get one-based line and column numbers
118        pub fn one_based(&self) -> OneBased {
119            unsafe {
120                OneBased {
121                    line: NonZeroUsize::new_unchecked(self.line + 1),
122                    column: NonZeroUsize::new_unchecked(self.column + 1),
123                }
124            }
125        }
126    }
127
128    impl From<(usize, usize)> for ZeroBased {
129        fn from((line, column): (usize, usize)) -> Self {
130            ZeroBased { line, column }
131        }
132    }
133
134    /// One-based (line, column) location
135    #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
136    pub struct OneBased {
137        pub line: NonZeroUsize,
138        pub column: NonZeroUsize,
139    }
140
141    impl OneBased {
142        pub fn new(line: usize, column: usize) -> Option<Self> {
143            let line = NonZeroUsize::new(line)?;
144            let column = NonZeroUsize::new(column)?;
145            Some(Self { line, column })
146        }
147
148        pub fn raw(&self) -> (usize, usize) {
149            (self.line.get(), self.column.get())
150        }
151
152        /// Get zero-based line and column numbers
153        pub fn zero_based(&self) -> ZeroBased {
154            ZeroBased {
155                line: self.line.get() - 1,
156                column: self.column.get() - 1,
157            }
158        }
159    }
160
161    impl From<(NonZeroUsize, NonZeroUsize)> for OneBased {
162        fn from((line, column): (NonZeroUsize, NonZeroUsize)) -> Self {
163            OneBased { line, column }
164        }
165    }
166}