anchor.rs

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