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#[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#[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#[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}