pub use pdfrum_doc::vt::hit::Place;
pub trait PlaceExt {
#[must_use]
fn start() -> Place;
#[must_use]
fn at_line_start(self) -> bool;
#[must_use]
fn same_line(self, other: Place) -> bool;
}
impl PlaceExt for Place {
fn start() -> Place {
Place::new(0, 0, None)
}
fn at_line_start(self) -> bool {
self.word.is_none()
}
fn same_line(self, other: Place) -> bool {
self.section == other.section && self.line == other.line
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Range {
begin: Place,
end: Place,
}
impl Range {
#[must_use]
pub fn new(a: Place, b: Place) -> Range {
if a <= b {
Range { begin: a, end: b }
} else {
Range { begin: b, end: a }
}
}
#[must_use]
pub fn empty_at(place: Place) -> Range {
Range {
begin: place,
end: place,
}
}
#[must_use]
pub fn begin(self) -> Place {
self.begin
}
#[must_use]
pub fn end(self) -> Place {
self.end
}
#[must_use]
pub fn is_empty(self) -> bool {
self.begin == self.end
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn places_order_lexicographically_over_the_triple() {
assert!(Place::new(0, 0, None) < Place::new(0, 0, Some(0)));
assert!(Place::new(0, 0, Some(9)) < Place::new(0, 1, None));
assert!(Place::new(0, 9, Some(9)) < Place::new(1, 0, None));
}
#[test]
fn the_start_is_before_the_first_character() {
assert!(Place::start().at_line_start());
assert_eq!(Place::start().word, None);
assert!(!Place::new(0, 0, Some(0)).at_line_start());
}
#[test]
fn same_line_ignores_the_character() {
assert!(Place::new(1, 2, Some(0)).same_line(Place::new(1, 2, Some(7))));
assert!(!Place::new(1, 2, Some(0)).same_line(Place::new(1, 3, Some(0))));
assert!(!Place::new(1, 2, Some(0)).same_line(Place::new(2, 2, Some(0))));
}
#[test]
fn a_range_normalizes_whichever_way_it_is_built() {
let lo = Place::new(0, 0, Some(1));
let hi = Place::new(0, 0, Some(5));
assert_eq!(Range::new(lo, hi), Range::new(hi, lo));
assert_eq!(Range::new(hi, lo).begin(), lo);
assert_eq!(Range::new(hi, lo).end(), hi);
}
#[test]
fn an_empty_range_covers_nothing() {
assert!(Range::empty_at(Place::start()).is_empty());
assert!(!Range::new(Place::start(), Place::new(0, 0, Some(0))).is_empty());
}
}