use std::fmt; use std::cmp::Ordering; #[derive(Copy,Clone)] pub struct Position { pub line: u32, pub column: u32, } impl Position { pub fn new( line: u32, column: u32 ) -> Self { Self { line, column, } } pub fn none() -> Self { Self { line: 0, column: 0, } } pub fn is_none(&self) -> bool { self.line == 0 || self.column == 0 } } impl fmt::Debug for Position { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if self.is_none() { write!(f, "none") } else { write!(f, "{}:{}", self.line, self.column ) } } } impl PartialOrd for Position { fn partial_cmp(&self, other: &Self) -> Option { let ord = self.line.partial_cmp( &other.line ); if Some(Ordering::Equal) == ord { self.column.partial_cmp( &other.column ) } else { ord } } } impl Ord for Position { fn cmp(&self, other: &Self) -> Ordering { let ord = self.line.cmp( &other.line ); if Ordering::Equal == ord { self.column.cmp( &other.column ) } else { ord } } } impl PartialEq for Position { fn eq(&self, other: &Self) -> bool { self.line == other.line && self.column == other.column } } impl Eq for Position {} #[derive(Copy,Clone)] pub struct Range { start: Position, end: Position, } impl Range { pub fn new( start: Position, end: Position ) -> Self { Self { start, end, } } pub fn include(&mut self, pos: &Position ) { if *pos < self.start { self.start = pos.clone(); } if *pos > self.end { self.end = pos.clone(); } } } impl fmt::Debug for Range { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}-{:?}", self.start, self.end ) } }