use crate::node_id::NodeId;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Position {
pub node: NodeId,
pub offset: usize,
}
impl Position {
pub fn new(node: NodeId, offset: usize) -> Self {
Self { node, offset }
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Range {
pub start: Position,
pub end: Position,
}
impl Range {
pub fn ordered_unchecked(start: Position, end: Position) -> Self {
Self { start, end }
}
pub fn is_collapsed(&self) -> bool {
self.start == self.end
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct SelectionSerial(u64);
impl SelectionSerial {
pub const fn new(n: u64) -> Self {
Self(n)
}
pub const fn get(self) -> u64 {
self.0
}
pub(crate) const fn next(self) -> Self {
Self(self.0.wrapping_add(1))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Selection {
pub anchor: Position,
pub focus: Position,
}
impl Selection {
pub fn new(anchor: Position, focus: Position) -> Self {
Self { anchor, focus }
}
pub fn caret(pos: Position) -> Self {
Self {
anchor: pos,
focus: pos,
}
}
pub fn is_collapsed(&self) -> bool {
self.anchor == self.focus
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::Dom;
fn node() -> (Dom, NodeId) {
let mut dom: Dom = Dom::new();
let t = dom.create_text_node("hello world");
(dom, t)
}
#[test]
fn position_construct() {
let (_, n) = node();
let p = Position::new(n, 3);
assert_eq!(p.node, n);
assert_eq!(p.offset, 3);
}
#[test]
fn selection_caret_is_collapsed() {
let (_, n) = node();
let sel = Selection::caret(Position::new(n, 5));
assert!(sel.is_collapsed());
assert_eq!(sel.anchor, sel.focus);
}
#[test]
fn selection_with_different_anchor_focus_is_not_collapsed() {
let (_, n) = node();
let sel = Selection::new(Position::new(n, 2), Position::new(n, 7));
assert!(!sel.is_collapsed());
}
#[test]
fn selection_preserves_direction() {
let (_, n) = node();
let sel = Selection::new(Position::new(n, 8), Position::new(n, 2));
assert_eq!(sel.anchor.offset, 8);
assert_eq!(sel.focus.offset, 2);
assert!(!sel.is_collapsed());
}
#[test]
fn range_is_collapsed_when_start_eq_end() {
let (_, n) = node();
let p = Position::new(n, 4);
let r = Range::ordered_unchecked(p, p);
assert!(r.is_collapsed());
}
}