spo_rhai/types/
position.rs1#![cfg(not(feature = "no_position"))]
3
4#[cfg(feature = "no_std")]
5use std::prelude::v1::*;
6use std::{
7 fmt,
8 ops::{Add, AddAssign},
9};
10
11#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy)]
20pub struct Position {
21 line: u16,
23 pos: u16,
25}
26
27impl Position {
28 pub const NONE: Self = Self { line: 0, pos: 0 };
30 pub const START: Self = Self { line: 1, pos: 0 };
32
33 #[inline]
43 #[must_use]
44 pub const fn new(line: u16, position: u16) -> Self {
45 assert!(line != 0, "line cannot be zero");
46
47 let _pos = position;
48
49 Self { line, pos: _pos }
50 }
51 #[inline]
55 #[must_use]
56 pub const fn line(self) -> Option<usize> {
57 if self.is_none() {
58 None
59 } else {
60 Some(self.line as usize)
61 }
62 }
63 #[inline]
67 #[must_use]
68 pub const fn position(self) -> Option<usize> {
69 if self.is_none() || self.pos == 0 {
70 None
71 } else {
72 Some(self.pos as usize)
73 }
74 }
75 #[inline]
77 pub(crate) fn advance(&mut self) {
78 assert!(!self.is_none(), "cannot advance Position::NONE");
79
80 self.pos = self.pos.saturating_add(1);
82 }
83 #[inline]
89 pub(crate) fn rewind(&mut self) {
90 assert!(!self.is_none(), "cannot rewind Position::NONE");
91 assert!(self.pos > 0, "cannot rewind at position 0");
92 self.pos -= 1;
93 }
94 #[inline]
96 pub(crate) fn new_line(&mut self) {
97 assert!(!self.is_none(), "cannot advance Position::NONE");
98
99 if self.line < u16::MAX {
101 self.line += 1;
102 self.pos = 0;
103 }
104 }
105 #[inline]
109 #[must_use]
110 pub const fn is_beginning_of_line(self) -> bool {
111 self.pos == 0 && !self.is_none()
112 }
113 #[inline]
117 #[must_use]
118 pub const fn is_none(self) -> bool {
119 self.line == 0 && self.pos == 0
120 }
121 #[inline]
125 #[must_use]
126 pub const fn or_else(self, pos: Self) -> Self {
127 if self.is_none() {
128 pos
129 } else {
130 self
131 }
132 }
133}
134
135impl Default for Position {
136 #[inline(always)]
137 #[must_use]
138 fn default() -> Self {
139 Self::START
140 }
141}
142
143impl fmt::Display for Position {
144 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
145 if self.is_none() {
146 write!(f, "none")
147 } else {
148 write!(f, "line {}, position {}", self.line, self.pos)
149 }
150 }
151}
152
153impl fmt::Debug for Position {
154 #[cold]
155 #[inline(never)]
156 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
157 if self.is_none() {
158 f.write_str("none")
159 } else if self.is_beginning_of_line() {
160 write!(f, "{}", self.line)
161 } else {
162 write!(f, "{}:{}", self.line, self.pos)
163 }
164 }
165}
166
167impl Add for Position {
168 type Output = Self;
169
170 fn add(self, rhs: Self) -> Self::Output {
171 if rhs.is_none() {
172 self
173 } else {
174 Self {
175 line: self.line + rhs.line - 1,
176 pos: if rhs.is_beginning_of_line() {
177 self.pos
178 } else {
179 self.pos + rhs.pos - 1
180 },
181 }
182 }
183 }
184}
185
186impl AddAssign for Position {
187 fn add_assign(&mut self, rhs: Self) {
188 *self = *self + rhs;
189 }
190}
191
192#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy)]
195pub struct Span {
196 start: Position,
198 end: Position,
200}
201
202impl Default for Span {
203 #[inline(always)]
204 #[must_use]
205 fn default() -> Self {
206 Self::NONE
207 }
208}
209
210impl Span {
211 pub const NONE: Self = Self::new(Position::NONE, Position::NONE);
213
214 #[inline(always)]
216 #[must_use]
217 pub const fn new(start: Position, end: Position) -> Self {
218 Self { start, end }
219 }
220 #[inline(always)]
224 #[must_use]
225 pub const fn is_none(self) -> bool {
226 self.start.is_none() && self.end.is_none()
227 }
228 #[inline(always)]
232 #[must_use]
233 pub const fn start(self) -> Position {
234 self.start
235 }
236 #[inline(always)]
240 #[must_use]
241 pub const fn end(self) -> Position {
242 self.end
243 }
244}
245
246impl fmt::Display for Span {
247 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
248 let _f = f;
249
250 match (self.start(), self.end()) {
251 (Position::NONE, Position::NONE) => write!(_f, "{:?}", Position::NONE),
252 (Position::NONE, end) => write!(_f, "..{end:?}"),
253 (start, Position::NONE) => write!(_f, "{start:?}"),
254 (start, end) if start.line() != end.line() => {
255 write!(_f, "{start:?}-{end:?}")
256 }
257 (start, end) => write!(
258 _f,
259 "{}:{}-{}",
260 start.line().unwrap(),
261 start.position().unwrap_or(0),
262 end.position().unwrap_or(0)
263 ),
264 }
265 }
266}
267
268impl fmt::Debug for Span {
269 #[cold]
270 #[inline(never)]
271 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
272 fmt::Display::fmt(self, f)
273 }
274}