Skip to main content

flams_utils/sourcerefs/
offsets.rs

1#![allow(clippy::inline_always)]
2
3use super::{LineCol, PositionKind, StringPosition};
4
5pub trait OffsetPosition: StringPosition + From<usize> + Into<usize>
6where
7    LineCol<Self>: StringPosition,
8{
9    fn offset(self) -> usize;
10}
11
12/// Number of bytes before this position
13#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
14#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default, Hash)]
15pub struct ByteOffset(pub usize);
16impl crate::__private::Sealed for ByteOffset {}
17impl std::ops::Add for ByteOffset {
18    type Output = Self;
19    #[inline(always)]
20    fn add(self, rhs: Self) -> Self::Output {
21        Self(self.0 + rhs.0)
22    }
23}
24impl std::ops::AddAssign for ByteOffset {
25    #[inline(always)]
26    fn add_assign(&mut self, rhs: Self) {
27        self.0 += rhs.0;
28    }
29}
30impl std::ops::Sub for ByteOffset {
31    type Output = Self;
32    #[inline(always)]
33    fn sub(self, rhs: Self) -> Self::Output {
34        Self(self.0.saturating_sub(rhs.0))
35    }
36}
37impl std::ops::SubAssign for ByteOffset {
38    #[inline(always)]
39    fn sub_assign(&mut self, rhs: Self) {
40        self.0 = self.0.saturating_sub(rhs.0);
41    }
42}
43impl std::fmt::Display for ByteOffset {
44    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
45        self.0.fmt(f)
46    }
47}
48impl StringPosition for ByteOffset {
49    const KIND: PositionKind = PositionKind::Byte;
50    #[inline(always)]
51    fn len(s: &str) -> Self {
52        Self(s.len())
53    }
54
55    #[inline]
56    #[allow(clippy::cast_possible_truncation)]
57    fn inc_by(&mut self, c: char) {
58        self.0 += c.len_utf8();
59    }
60    fn inc_newline(&mut self, crlf: bool) {
61        if crlf {
62            self.0 += 2;
63        } else {
64            self.0 += 1;
65        }
66    }
67
68    #[inline]
69    fn inc_offset_by(&mut self, text: &str) {
70        self.0 += text.len();
71    }
72
73    #[inline(always)]
74    fn from_other<P: StringPosition>(p: P, source: &str) -> Self {
75        use PositionKind as K;
76        unsafe {
77            match P::KIND {
78                K::None => Self::default(),
79                K::Byte => std::mem::transmute_copy(&p),
80                K::Char => super::convert::char_to_byte(std::mem::transmute_copy(&p), source),
81                K::Utf16 => super::convert::utf16_to_byte(std::mem::transmute_copy(&p), source),
82                K::LineColByte => {
83                    super::convert::linecolbyte_to_byte(std::mem::transmute_copy(&p), source)
84                }
85                K::LineColChar => {
86                    super::convert::linecolchar_to_byte(std::mem::transmute_copy(&p), source)
87                }
88                K::LineColUtf16 => {
89                    super::convert::linecolutf16_to_byte(std::mem::transmute_copy(&p), source)
90                }
91            }
92        }
93    }
94}
95impl From<usize> for ByteOffset {
96    #[inline(always)]
97    fn from(value: usize) -> Self {
98        Self(value)
99    }
100}
101impl From<ByteOffset> for usize {
102    #[inline(always)]
103    fn from(value: ByteOffset) -> Self {
104        value.0
105    }
106}
107impl OffsetPosition for ByteOffset {
108    #[inline(always)]
109    fn offset(self) -> usize {
110        self.0
111    }
112}
113
114/// Number of characters before this position
115#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
116#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default, Hash)]
117pub struct CharOffset(pub usize);
118impl crate::__private::Sealed for CharOffset {}
119impl std::ops::Add for CharOffset {
120    type Output = Self;
121    #[inline(always)]
122    fn add(self, rhs: Self) -> Self::Output {
123        Self(self.0 + rhs.0)
124    }
125}
126impl std::ops::AddAssign for CharOffset {
127    #[inline(always)]
128    fn add_assign(&mut self, rhs: Self) {
129        self.0 += rhs.0;
130    }
131}
132impl std::ops::Sub for CharOffset {
133    type Output = Self;
134    #[inline(always)]
135    fn sub(self, rhs: Self) -> Self::Output {
136        Self(self.0.saturating_sub(rhs.0))
137    }
138}
139impl std::ops::SubAssign for CharOffset {
140    #[inline(always)]
141    fn sub_assign(&mut self, rhs: Self) {
142        self.0 = self.0.saturating_sub(rhs.0);
143    }
144}
145impl std::fmt::Display for CharOffset {
146    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
147        self.0.fmt(f)
148    }
149}
150impl StringPosition for CharOffset {
151    const KIND: PositionKind = PositionKind::Char;
152
153    #[inline]
154    fn len(s: &str) -> Self {
155        Self(s.chars().count())
156    }
157
158    #[inline]
159    fn inc_by(&mut self, _: char) {
160        self.0 += 1;
161    }
162    #[inline]
163    fn inc_offset_by(&mut self, text: &str) {
164        self.0 += text.chars().count();
165    }
166
167    fn inc_newline(&mut self, crlf: bool) {
168        if crlf {
169            self.0 += 2;
170        } else {
171            self.0 += 1;
172        }
173    }
174
175    #[inline(always)]
176    fn from_other<P: StringPosition>(p: P, source: &str) -> Self {
177        use PositionKind as K;
178        unsafe {
179            match P::KIND {
180                K::None => Self::default(),
181                K::Char => std::mem::transmute_copy(&p),
182                K::Byte => super::convert::byte_to_char(std::mem::transmute_copy(&p), source),
183                K::Utf16 => super::convert::utf16_to_char(std::mem::transmute_copy(&p), source),
184                K::LineColByte => {
185                    super::convert::linecolbyte_to_char(std::mem::transmute_copy(&p), source)
186                }
187                K::LineColChar => {
188                    super::convert::linecolchar_to_char(std::mem::transmute_copy(&p), source)
189                }
190                K::LineColUtf16 => {
191                    super::convert::linecolutf16_to_char(std::mem::transmute_copy(&p), source)
192                }
193            }
194        }
195    }
196}
197impl From<usize> for CharOffset {
198    #[inline(always)]
199    fn from(value: usize) -> Self {
200        Self(value)
201    }
202}
203impl From<CharOffset> for usize {
204    #[inline(always)]
205    fn from(value: CharOffset) -> Self {
206        value.0
207    }
208}
209impl OffsetPosition for CharOffset {
210    #[inline(always)]
211    fn offset(self) -> usize {
212        self.0
213    }
214}
215
216/// Number of UTF-16 codepoints before this position
217#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
218#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default, Hash)]
219pub struct Utf16Offset(pub usize);
220impl crate::__private::Sealed for Utf16Offset {}
221impl std::ops::Add for Utf16Offset {
222    type Output = Self;
223    #[inline(always)]
224    fn add(self, rhs: Self) -> Self::Output {
225        Self(self.0 + rhs.0)
226    }
227}
228impl std::ops::AddAssign for Utf16Offset {
229    #[inline(always)]
230    fn add_assign(&mut self, rhs: Self) {
231        self.0 += rhs.0;
232    }
233}
234impl std::ops::Sub for Utf16Offset {
235    type Output = Self;
236    #[inline(always)]
237    fn sub(self, rhs: Self) -> Self::Output {
238        Self(self.0.saturating_sub(rhs.0))
239    }
240}
241impl std::ops::SubAssign for Utf16Offset {
242    #[inline(always)]
243    fn sub_assign(&mut self, rhs: Self) {
244        self.0 = self.0.saturating_sub(rhs.0);
245    }
246}
247impl std::fmt::Display for Utf16Offset {
248    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
249        self.0.fmt(f)
250    }
251}
252impl StringPosition for Utf16Offset {
253    const KIND: PositionKind = PositionKind::Utf16;
254
255    #[inline]
256    fn len(s: &str) -> Self {
257        Self(s.chars().map(char::len_utf16).sum())
258    }
259
260    #[inline]
261    fn inc_by(&mut self, c: char) {
262        self.0 += c.len_utf16();
263    }
264
265    #[inline]
266    fn inc_offset_by(&mut self, text: &str) {
267        self.0 += text.chars().map(char::len_utf16).sum::<usize>();
268    }
269
270    fn inc_newline(&mut self, crlf: bool) {
271        if crlf {
272            self.0 += 2;
273        } else {
274            self.0 += 1;
275        }
276    }
277
278    #[inline(always)]
279    fn from_other<P: StringPosition>(p: P, source: &str) -> Self {
280        use PositionKind as K;
281        unsafe {
282            match P::KIND {
283                K::None => Self::default(),
284                K::Utf16 => std::mem::transmute_copy(&p),
285                K::Byte => super::convert::byte_to_utf16(std::mem::transmute_copy(&p), source),
286                K::Char => super::convert::char_to_utf16(std::mem::transmute_copy(&p), source),
287                K::LineColByte => {
288                    super::convert::linecolbyte_to_utf16(std::mem::transmute_copy(&p), source)
289                }
290                K::LineColChar => {
291                    super::convert::linecolchar_to_utf16(std::mem::transmute_copy(&p), source)
292                }
293                K::LineColUtf16 => {
294                    super::convert::linecolutf16_to_utf16(std::mem::transmute_copy(&p), source)
295                }
296            }
297        }
298    }
299}
300
301impl From<usize> for Utf16Offset {
302    #[inline(always)]
303    fn from(value: usize) -> Self {
304        Self(value)
305    }
306}
307impl From<Utf16Offset> for usize {
308    #[inline(always)]
309    fn from(value: Utf16Offset) -> Self {
310        value.0
311    }
312}
313impl OffsetPosition for Utf16Offset {
314    #[inline(always)]
315    fn offset(self) -> usize {
316        self.0
317    }
318}