#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct Position {
pub row: usize,
pub col: usize,
}
impl Position {
pub const fn new(row: usize, col: usize) -> Self {
Self { row, col }
}
pub fn byte_offset(self, line: &str) -> usize {
line.char_indices()
.nth(self.col)
.map(|(b, _)| b)
.unwrap_or(line.len())
}
}
#[cfg(test)]
mod tests {
use super::Position;
#[test]
fn byte_offset_ascii() {
assert_eq!(Position::new(0, 0).byte_offset("hello"), 0);
assert_eq!(Position::new(0, 3).byte_offset("hello"), 3);
assert_eq!(Position::new(0, 5).byte_offset("hello"), 5);
assert_eq!(Position::new(0, 99).byte_offset("hello"), 5);
}
#[test]
fn byte_offset_utf8() {
let line = "tablé";
assert_eq!(Position::new(0, 4).byte_offset(line), 4);
assert_eq!(Position::new(0, 5).byte_offset(line), 6);
}
#[test]
fn ord_is_row_major() {
assert!(Position::new(0, 5) < Position::new(1, 0));
assert!(Position::new(2, 0) > Position::new(1, 999));
assert!(Position::new(1, 3) < Position::new(1, 4));
}
}