use crate::Point; use super::{Buffer, Content}; use anyhow::Result; use std::{cmp::Ordering, ops::Range}; use sum_tree::Bias; #[derive(Clone, Eq, PartialEq, Debug, Hash)] pub struct Anchor { pub offset: usize, pub bias: Bias, pub version: clock::Global, } #[derive(Clone)] pub struct AnchorMap { pub(crate) version: clock::Global, pub(crate) entries: Vec<((usize, Bias), T)>, } #[derive(Clone)] pub struct AnchorSet(pub(crate) AnchorMap<()>); #[derive(Clone)] pub struct AnchorRangeMap { pub(crate) version: clock::Global, pub(crate) entries: Vec<(Range<(usize, Bias)>, T)>, } #[derive(Clone)] pub struct AnchorRangeSet(pub(crate) AnchorRangeMap<()>); impl Anchor { pub fn min() -> Self { Self { offset: 0, bias: Bias::Left, version: Default::default(), } } pub fn max() -> Self { Self { offset: usize::MAX, bias: Bias::Right, version: Default::default(), } } pub fn cmp<'a>(&self, other: &Anchor, buffer: impl Into>) -> Result { let buffer = buffer.into(); if self == other { return Ok(Ordering::Equal); } let offset_comparison = if self.version == other.version { self.offset.cmp(&other.offset) } else { buffer .full_offset_for_anchor(self) .cmp(&buffer.full_offset_for_anchor(other)) }; Ok(offset_comparison.then_with(|| self.bias.cmp(&other.bias))) } pub fn bias_left(&self, buffer: &Buffer) -> Anchor { if self.bias == Bias::Left { self.clone() } else { buffer.anchor_before(self) } } pub fn bias_right(&self, buffer: &Buffer) -> Anchor { if self.bias == Bias::Right { self.clone() } else { buffer.anchor_after(self) } } } impl AnchorMap { pub fn to_points<'a>( &'a self, content: impl Into> + 'a, ) -> impl Iterator + 'a { let content = content.into(); content .summaries_for_anchors(self) .map(move |(sum, value)| (sum.lines, value)) } pub fn version(&self) -> &clock::Global { &self.version } } impl AnchorSet { pub fn to_points<'a>( &'a self, content: impl Into> + 'a, ) -> impl Iterator + 'a { self.0.to_points(content).map(move |(point, _)| point) } } impl AnchorRangeMap { pub fn to_point_ranges<'a>( &'a self, content: impl Into> + 'a, ) -> impl Iterator, &'a T)> + 'a { let content = content.into(); content .summaries_for_anchor_ranges(self) .map(move |(range, value)| ((range.start.lines..range.end.lines), value)) } pub fn version(&self) -> &clock::Global { &self.version } } impl AnchorRangeSet { pub fn to_point_ranges<'a>( &'a self, content: impl Into> + 'a, ) -> impl Iterator> + 'a { self.0.to_point_ranges(content).map(|(range, _)| range) } pub fn version(&self) -> &clock::Global { self.0.version() } } pub trait AnchorRangeExt { fn cmp<'a>(&self, b: &Range, buffer: impl Into>) -> Result; } impl AnchorRangeExt for Range { fn cmp<'a>(&self, other: &Range, buffer: impl Into>) -> Result { let buffer = buffer.into(); Ok(match self.start.cmp(&other.start, &buffer)? { Ordering::Equal => other.end.cmp(&self.end, buffer)?, ord @ _ => ord, }) } }