anchor.rs

  1use super::Buffer;
  2use crate::{sum_tree, time};
  3use anyhow::Result;
  4use std::{cmp::Ordering, ops::Range};
  5
  6#[derive(Clone, Eq, PartialEq, Debug, Hash)]
  7pub enum Anchor {
  8    Start,
  9    End,
 10    Middle {
 11        offset: usize,
 12        bias: AnchorBias,
 13        version: time::Global,
 14    },
 15}
 16
 17#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
 18pub enum AnchorBias {
 19    Left,
 20    Right,
 21}
 22
 23impl AnchorBias {
 24    pub fn to_seek_bias(self) -> sum_tree::SeekBias {
 25        match self {
 26            AnchorBias::Left => sum_tree::SeekBias::Left,
 27            AnchorBias::Right => sum_tree::SeekBias::Right,
 28        }
 29    }
 30}
 31
 32impl PartialOrd for AnchorBias {
 33    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
 34        Some(self.cmp(other))
 35    }
 36}
 37
 38impl Ord for AnchorBias {
 39    fn cmp(&self, other: &Self) -> Ordering {
 40        use AnchorBias::*;
 41
 42        if self == other {
 43            return Ordering::Equal;
 44        }
 45
 46        match (self, other) {
 47            (Left, _) => Ordering::Less,
 48            (Right, _) => Ordering::Greater,
 49        }
 50    }
 51}
 52
 53impl Anchor {
 54    pub fn cmp(&self, other: &Anchor, buffer: &Buffer) -> Result<Ordering> {
 55        if self == other {
 56            return Ok(Ordering::Equal);
 57        }
 58
 59        Ok(match (self, other) {
 60            (Anchor::Start, _) | (_, Anchor::End) => Ordering::Less,
 61            (Anchor::End, _) | (_, Anchor::Start) => Ordering::Greater,
 62            (
 63                Anchor::Middle {
 64                    bias: self_bias, ..
 65                },
 66                Anchor::Middle {
 67                    bias: other_bias, ..
 68                },
 69            ) => buffer
 70                .fragment_ix_for_anchor(self)
 71                .cmp(&buffer.fragment_ix_for_anchor(other))
 72                .then_with(|| self_bias.cmp(&other_bias)),
 73        })
 74    }
 75
 76    pub fn bias_left(&self, buffer: &Buffer) -> Anchor {
 77        match self {
 78            Anchor::Start
 79            | Anchor::Middle {
 80                bias: AnchorBias::Left,
 81                ..
 82            } => self.clone(),
 83            _ => buffer.anchor_before(self),
 84        }
 85    }
 86
 87    pub fn bias_right(&self, buffer: &Buffer) -> Anchor {
 88        match self {
 89            Anchor::End
 90            | Anchor::Middle {
 91                bias: AnchorBias::Right,
 92                ..
 93            } => self.clone(),
 94            _ => buffer.anchor_after(self),
 95        }
 96    }
 97}
 98
 99pub trait AnchorRangeExt {
100    fn cmp(&self, b: &Range<Anchor>, buffer: &Buffer) -> Result<Ordering>;
101}
102
103impl AnchorRangeExt for Range<Anchor> {
104    fn cmp(&self, other: &Range<Anchor>, buffer: &Buffer) -> Result<Ordering> {
105        Ok(match self.start.cmp(&other.start, buffer)? {
106            Ordering::Equal => other.end.cmp(&self.end, buffer)?,
107            ord @ _ => ord,
108        })
109    }
110}