use super::{ExcerptId, MultiBufferSnapshot, ToOffset, ToOffsetUtf16, ToPoint}; use language::{OffsetUtf16, Point, TextDimension}; use std::{ cmp::Ordering, ops::{Range, Sub}, }; use sum_tree::Bias; #[derive(Clone, Copy, Eq, PartialEq, Debug, Hash)] pub struct Anchor { pub buffer_id: Option, pub excerpt_id: ExcerptId, pub text_anchor: text::Anchor, } impl Anchor { pub fn min() -> Self { Self { buffer_id: None, excerpt_id: ExcerptId::min(), text_anchor: text::Anchor::MIN, } } pub fn max() -> Self { Self { buffer_id: None, excerpt_id: ExcerptId::max(), text_anchor: text::Anchor::MAX, } } pub fn cmp(&self, other: &Anchor, snapshot: &MultiBufferSnapshot) -> Ordering { let excerpt_id_cmp = self.excerpt_id.cmp(&other.excerpt_id, snapshot); if excerpt_id_cmp.is_eq() { if self.excerpt_id == ExcerptId::min() || self.excerpt_id == ExcerptId::max() { Ordering::Equal } else if let Some(excerpt) = snapshot.excerpt(self.excerpt_id) { self.text_anchor.cmp(&other.text_anchor, &excerpt.buffer) } else { Ordering::Equal } } else { excerpt_id_cmp } } pub fn bias(&self) -> Bias { self.text_anchor.bias } pub fn bias_left(&self, snapshot: &MultiBufferSnapshot) -> Anchor { if self.text_anchor.bias != Bias::Left { if let Some(excerpt) = snapshot.excerpt(self.excerpt_id) { return Self { buffer_id: self.buffer_id, excerpt_id: self.excerpt_id.clone(), text_anchor: self.text_anchor.bias_left(&excerpt.buffer), }; } } self.clone() } pub fn bias_right(&self, snapshot: &MultiBufferSnapshot) -> Anchor { if self.text_anchor.bias != Bias::Right { if let Some(excerpt) = snapshot.excerpt(self.excerpt_id) { return Self { buffer_id: self.buffer_id, excerpt_id: self.excerpt_id.clone(), text_anchor: self.text_anchor.bias_right(&excerpt.buffer), }; } } self.clone() } pub fn summary(&self, snapshot: &MultiBufferSnapshot) -> D where D: TextDimension + Ord + Sub, { snapshot.summary_for_anchor(self) } pub fn is_valid(&self, snapshot: &MultiBufferSnapshot) -> bool { if *self == Anchor::min() || *self == Anchor::max() { true } else if let Some(excerpt) = snapshot.excerpt(self.excerpt_id) { excerpt.contains(self) && (self.text_anchor == excerpt.range.context.start || self.text_anchor == excerpt.range.context.end || self.text_anchor.is_valid(&excerpt.buffer)) } else { false } } } impl ToOffset for Anchor { fn to_offset(&self, snapshot: &MultiBufferSnapshot) -> usize { self.summary(snapshot) } } impl ToOffsetUtf16 for Anchor { fn to_offset_utf16(&self, snapshot: &MultiBufferSnapshot) -> OffsetUtf16 { self.summary(snapshot) } } impl ToPoint for Anchor { fn to_point<'a>(&self, snapshot: &MultiBufferSnapshot) -> Point { self.summary(snapshot) } } pub trait AnchorRangeExt { fn cmp(&self, b: &Range, buffer: &MultiBufferSnapshot) -> Ordering; fn to_offset(&self, content: &MultiBufferSnapshot) -> Range; fn to_point(&self, content: &MultiBufferSnapshot) -> Range; } impl AnchorRangeExt for Range { fn cmp(&self, other: &Range, buffer: &MultiBufferSnapshot) -> Ordering { match self.start.cmp(&other.start, buffer) { Ordering::Equal => other.end.cmp(&self.end, buffer), ord => ord, } } fn to_offset(&self, content: &MultiBufferSnapshot) -> Range { self.start.to_offset(content)..self.end.to_offset(content) } fn to_point(&self, content: &MultiBufferSnapshot) -> Range { self.start.to_point(content)..self.end.to_point(content) } }