luau_lexer/
position.rs

1//! The [`Position`] struct.
2
3/// Each component (line and character) in the [`Position`] struct.
4pub type PositionComponent = u32;
5
6/// A struct representing a specific point in a document. Lines and characters are
7/// zero-based.
8#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
9#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
10pub struct Position {
11    /// The line in which this position points to, starting from 0.
12    pub line: PositionComponent,
13
14    /// The character in the [`line`](Position::line) that this position points to,
15    /// starting from 0.
16    pub character: PositionComponent,
17}
18
19impl Position {
20    /// The largest value that can be represented by a [`Position`].
21    pub const MAX: Self = Self::new(PositionComponent::MAX, PositionComponent::MAX);
22
23    /// The smallest value that can be represented by a [`Position`].
24    pub const MIN: Self = Self::new(PositionComponent::MIN, PositionComponent::MIN);
25
26    /// Create a new [`Position`].
27    #[inline]
28    pub const fn new(line: PositionComponent, character: PositionComponent) -> Self {
29        Self { line, character }
30    }
31
32    /// Offsets the current position by lines and characters. If you're adding both
33    /// lines and characters, making sure to set characters to `0` before calling
34    /// this function to ensure correct results.
35    #[inline]
36    pub fn offset(&mut self, lines: i32, characters: i32) {
37        self.line = self.line.saturating_add_signed(lines);
38        self.character = self.character.saturating_add_signed(characters);
39    }
40
41    /// Sets line to a specific value.
42    #[inline]
43    pub fn set_line(&mut self, line: u32) {
44        self.line = line;
45    }
46
47    /// Sets character to a specific value.
48    #[inline]
49    pub fn set_character(&mut self, character: u32) {
50        self.character = character;
51    }
52
53    /// Checks whether or not this position is between the 2 passed positions.
54    #[inline]
55    pub fn is_in_bounds(self, start: Self, end: Self) -> bool {
56        self.is_after(start) & self.is_before(end)
57    }
58
59    /// Checks whether or not this position is after the passed position.
60    #[inline]
61    pub fn is_after(self, position: Position) -> bool {
62        self.line > position.line
63            || position.line == self.line && self.character >= position.character
64    }
65
66    /// Checks whether or not this position is before the passed position.
67    #[inline]
68    pub fn is_before(self, position: Position) -> bool {
69        self.line < position.line
70            || position.line == self.line && self.character <= position.character
71    }
72}