use std::{fmt, hash};
use super::Input;
#[derive(Clone, Copy, Debug, Eq)]
pub struct Position {
pub(super) offset: u32,
pub(super) line: u16,
pub(super) column: u16,
}
impl Position {
pub fn new(offset: usize, line: usize, column: usize) -> Self {
let line = line.clamp(1, u16::MAX as usize);
let column = column.clamp(1, u16::MAX as usize);
Self {
offset: offset as u32,
line: line as u16,
column: column as u16,
}
}
#[inline]
pub const fn offset(&self) -> usize {
self.offset as usize
}
#[inline]
pub const fn line(&self) -> usize {
self.line as usize
}
#[inline]
pub const fn column(&self) -> usize {
self.column as usize
}
}
impl Default for Position {
fn default() -> Self {
Self {
offset: 0,
line: 1,
column: 1,
}
}
}
impl PartialEq for Position {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.offset == other.offset
}
}
impl Ord for Position {
#[inline]
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.offset.cmp(&other.offset)
}
}
impl PartialOrd for Position {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl hash::Hash for Position {
#[inline]
fn hash<H: hash::Hasher>(&self, state: &mut H) {
self.offset.hash(state);
}
}
impl fmt::Display for Position {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if f.alternate() {
write!(f, "{}:{}:{}", self.offset, self.line, self.column)
} else {
write!(f, "{}:{}", self.line, self.column)
}
}
}
impl From<Input<'_>> for Position {
#[inline]
fn from(input: Input<'_>) -> Self {
input.position()
}
}
impl From<&Input<'_>> for Position {
#[inline]
fn from(input: &Input<'_>) -> Self {
input.position()
}
}
impl From<&mut Input<'_>> for Position {
#[inline]
fn from(input: &mut Input<'_>) -> Self {
input.position()
}
}
impl From<&&mut Input<'_>> for Position {
#[inline]
fn from(input: &&mut Input<'_>) -> Self {
input.position()
}
}