#![allow(dead_code)]
use std::cmp::Ordering;
use std::fmt::{Display, Formatter};
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Coords {
pub absolute: usize,
pub line: usize,
pub column: usize,
}
impl Coords {
pub fn from_coords(value: &Coords) -> Self {
Coords {
line: value.line,
column: value.column,
absolute: value.absolute,
}
}
pub fn from_line(line: usize) -> Self {
Coords {
absolute: 0,
line,
column: 0,
}
}
pub fn is_before(&self, other: &Coords) -> bool {
self < other
}
pub fn is_after(&self, other: &Coords) -> bool {
self > other
}
#[inline]
pub fn copy_from(&mut self, other: &Coords) {
self.line = other.line;
self.column = other.column;
self.absolute = other.absolute;
}
#[inline]
pub fn increment(&mut self) {
self.column += 1;
self.absolute += 1;
}
#[inline]
pub fn decrement(&mut self) {
self.column -= 1;
self.absolute -= 1;
}
#[inline]
pub fn increment_newline(&mut self) {
self.column = 0;
self.line += 1;
self.absolute += 1;
}
#[inline]
pub fn copy_increment(&self) -> Self {
Coords {
line: self.line,
column: self.column + 1,
absolute: self.absolute + 1,
}
}
#[inline]
pub fn copy_increment_newline(&self) -> Self {
Coords {
line: self.line + 1,
column: 1,
absolute: self.absolute + 1,
}
}
#[inline]
pub fn copy_decrement(&mut self) -> Self {
Coords {
line: self.line,
column: self.column - 1,
absolute: self.absolute - 1,
}
}
}
impl Display for Coords {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"[abs: {}, line: {}, column: {}]",
self.absolute, self.line, self.column
)
}
}
impl Default for Coords {
fn default() -> Self {
Coords {
absolute: 0,
line: 0,
column: 0,
}
}
}
impl Eq for Coords {}
impl PartialOrd<Self> for Coords {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
match self.absolute.cmp(&other.absolute) {
Ordering::Less => Some(Ordering::Less),
Ordering::Equal => Some(Ordering::Equal),
Ordering::Greater => Some(Ordering::Greater),
}
}
}
impl Ord for Coords {
fn cmp(&self, other: &Self) -> Ordering {
self.absolute.cmp(&other.absolute)
}
}
#[cfg(test)]
mod test {
use crate::char::coords::Coords;
#[test]
fn is_before_behaves_as_you_would_expect() {
let c1 = Coords {
line: 1,
column: 1,
absolute: 1,
};
let c2 = Coords {
line: 1,
column: 12,
absolute: 12,
};
assert!(c1.is_before(&c2));
assert!(!c2.is_before(&c1));
}
#[test]
fn is_after_behaves_correctly() {
let c1 = Coords {
line: 1,
column: 1,
absolute: 1,
};
let c2 = Coords {
line: 1,
column: 12,
absolute: 12,
};
assert!(!c1.is_after(&c2));
assert!(c2.is_after(&c1))
}
#[test]
fn equality_between_coords() {
let c1 = Coords {
line: 1,
column: 1,
absolute: 1,
};
let c2 = Coords {
line: 1,
column: 1,
absolute: 1,
};
assert_eq!(c1, c2)
}
#[test]
fn inc_works() {
let mut c1 = Coords::from_line(1);
for _ in 1..=5 {
c1 = c1.copy_increment();
}
assert_eq!(
c1,
Coords {
line: 1,
column: 5,
absolute: 5
}
)
}
#[test]
fn inc_newline_works() {
let mut c1 = Coords::default();
let mut c2 = Coords::default();
assert_eq!(c1, c2);
c1 = c1.copy_increment_newline();
assert!(c1 > c2);
c2 = c2.copy_increment_newline();
assert_eq!(c1, c2)
}
#[test]
fn dec_works() {
let mut c1 = Coords::from_line(1);
for _ in 1..=5 {
c1.increment();
}
for _ in 1..=3 {
c1.decrement()
}
assert_eq!(
c1,
Coords {
line: 1,
column: 2,
absolute: 2
}
)
}
#[test]
#[should_panic]
fn dec_panics() {
let mut c1 = Coords::from_line(1);
for _ in 1..=5 {
c1.increment();
}
for _ in 1..=6 {
c1.decrement()
}
}
#[test]
fn merge_should_take_all_values_from_source() {
let c1 = Coords::default().copy_increment();
let mut c2 = Coords::default();
c2.copy_from(&c1);
assert_eq!(c1, c2)
}
}