#[cfg(feature = "npm")]
use napi_derive::napi;
use serde::Serialize;
#[cfg_attr(feature = "npm", napi(object))]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize)]
pub struct Position {
pub line: u32,
pub column: u32,
pub offset: u32,
}
#[cfg_attr(feature = "npm", napi(object))]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize)]
pub struct Span {
pub start: Position,
pub end: Position,
}
impl Span {
pub fn new(start: Position, end: Position) -> Self {
Self { start, end }
}
}
impl Position {
pub fn new(line: usize, column: usize, offset: usize) -> Self {
Self {
line: line.try_into().unwrap(),
column: column.try_into().unwrap(),
offset: offset.try_into().unwrap(),
}
}
}
#[cfg(test)]
mod tests {
use super::{Position, Span};
#[test]
fn defaults_point_to_the_document_start() {
let pos = Position::default();
assert_eq!((pos.line, pos.column, pos.offset), (0, 0, 0));
let span = Span::default();
assert_eq!(span.start, pos);
assert_eq!(span.end, pos);
}
#[test]
fn new_stores_all_three_coordinates() {
let pos = Position::new(3, 7, 42);
assert_eq!(pos.line, 3);
assert_eq!(pos.column, 7);
assert_eq!(pos.offset, 42);
}
#[test]
fn span_new_builds_half_open_range() {
let start = Position::new(0, 4, 4);
let end = Position::new(0, 9, 9);
let span = Span::new(start, end);
assert_eq!(span.start, start);
assert_eq!(span.end, end);
}
#[test]
fn spans_compare_by_value() {
let a = Span::new(Position::new(1, 0, 5), Position::new(1, 3, 8));
let b = Span::new(Position::new(1, 0, 5), Position::new(1, 3, 8));
let c = Span::new(Position::new(1, 0, 5), Position::new(1, 4, 9));
assert_eq!(a, b);
assert_ne!(a, c);
}
}