#![allow(
incomplete_features,
clippy::arc_with_non_send_sync,
clippy::too_many_arguments
)]
#![feature(generic_const_exprs)]
#![allow(
clippy::collapsible_if,
clippy::inline_always,
clippy::needless_return,
clippy::redundant_field_names,
clippy::type_complexity
)]
mod rope;
mod rope_builder;
mod slice;
mod slice_utils;
mod tree;
pub mod iter;
use std::{
cmp::Ordering,
fmt::Debug,
ops::{Add, Bound, Range, RangeFrom, RangeFull, RangeTo, Sub},
};
pub use crate::{
rope::Rope,
rope_builder::RopeBuilder,
slice::RopeSlice,
tree::{max_children, max_len},
};
pub trait FallibleOrd {
fn fallible_cmp(&self, other: &Self) -> Ordering;
}
pub trait Measurable: Clone {
type Measure: Debug
+ Default
+ Clone
+ Copy
+ PartialEq
+ Eq
+ Add<Output = Self::Measure>
+ Sub<Output = Self::Measure>
+ FallibleOrd;
fn measure(&self) -> Self::Measure;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Width(pub usize);
impl PartialOrd for Width {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Width {
fn cmp(&self, other: &Self) -> Ordering {
self.0.fallible_cmp(&other.0)
}
}
impl FallibleOrd for usize {
fn fallible_cmp(&self, other: &Self) -> Ordering {
self.cmp(other)
}
}
impl Measurable for Width {
type Measure = usize;
fn measure(&self) -> Self::Measure {
self.0
}
}
pub type Result<T, M> = std::result::Result<T, Error<M>>;
#[derive(Clone, Copy)]
#[non_exhaustive]
pub enum Error<M: Measurable> {
IndexOutOfBounds(usize, usize),
MeasureOutOfBounds(M::Measure, M::Measure),
IndexRangeInvalid(usize, usize),
MeasureRangeInvalid(Option<M::Measure>, Option<M::Measure>),
IndexRangeOutOfBounds(Option<usize>, Option<usize>, usize),
MeasureRangeOutOfBounds(Option<M::Measure>, Option<M::Measure>, M::Measure),
}
impl<M: Measurable> std::fmt::Debug for Error<M> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match *self {
Error::IndexOutOfBounds(index, len) => {
write!(
f,
"Index out of bounds: index {}, Rope/RopeSlice length {}",
index, len
)
}
Error::MeasureOutOfBounds(measure, max) => {
write!(
f,
"Measure out of bounds: measure {:?}, Rope/RopeSlice measure {:?}",
measure, max
)
}
Error::IndexRangeInvalid(start_index, end_index) => {
write!(
f,
"Invalid index range {}..{}: start must be <= end",
start_index, end_index
)
}
Error::MeasureRangeInvalid(start_measure, end_measure) => {
write!(
f,
"Invalid measure range {:?}..{:?}: start must be <= end",
start_measure, end_measure
)
}
Error::IndexRangeOutOfBounds(start, end, len) => {
write!(f, "Index range out of bounds: index range ")?;
write_range(f, start, end)?;
write!(f, ", Rope/RopeSlice byte length {}", len)
}
Error::MeasureRangeOutOfBounds(start, end, measure) => {
write!(f, "Measure range out of bounds: measure range ")?;
write_range(f, start, end)?;
write!(f, ", Rope/RopeSlice measure {:?}", measure)
}
}
}
}
impl<M: Measurable> std::error::Error for Error<M> {}
impl<M: Measurable> std::fmt::Display for Error<M> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Debug::fmt(self, f)
}
}
fn write_range<T: Debug>(
f: &mut std::fmt::Formatter<'_>,
start_idx: Option<T>,
end_idx: Option<T>,
) -> std::fmt::Result {
match (start_idx, end_idx) {
(None, None) => write!(f, ".."),
(None, Some(end)) => write!(f, "..{:?}", end),
(Some(start), None) => write!(f, "{:?}..", start),
(Some(start), Some(end)) => write!(f, "{:?}..{:?}", start, end),
}
}
#[inline(always)]
fn start_bound_to_num(b: Bound<&usize>) -> Option<usize> {
match b {
Bound::Included(n) => Some(*n),
Bound::Excluded(n) => Some(*n + 1),
Bound::Unbounded => None,
}
}
#[inline(always)]
fn end_bound_to_num(b: Bound<&usize>) -> Option<usize> {
match b {
Bound::Included(n) => Some(*n + 1),
Bound::Excluded(n) => Some(*n),
Bound::Unbounded => None,
}
}
mod hidden {
use std::ops::{Range, RangeFrom, RangeFull, RangeTo};
pub trait Internal {}
impl<T> Internal for Range<T> {}
impl<T> Internal for RangeFrom<T> {}
impl<T> Internal for RangeTo<T> {}
impl Internal for RangeFull {}
}
pub trait MeasureRange<M: Measurable>: hidden::Internal {
fn start_bound(&self) -> Option<&M::Measure>;
fn end_bound(&self) -> Option<&M::Measure>;
}
impl<M: Measurable> MeasureRange<M> for Range<M::Measure> {
fn start_bound(&self) -> Option<&M::Measure> {
Some(&self.start)
}
fn end_bound(&self) -> Option<&M::Measure> {
Some(&self.end)
}
}
impl<M: Measurable> MeasureRange<M> for RangeFrom<M::Measure> {
fn start_bound(&self) -> Option<&M::Measure> {
Some(&self.start)
}
fn end_bound(&self) -> Option<&M::Measure> {
None
}
}
impl<M: Measurable> MeasureRange<M> for RangeTo<M::Measure> {
fn start_bound(&self) -> Option<&M::Measure> {
None
}
fn end_bound(&self) -> Option<&M::Measure> {
Some(&self.end)
}
}
impl<M: Measurable> MeasureRange<M> for RangeFull {
fn start_bound(&self) -> Option<&M::Measure> {
None
}
fn end_bound(&self) -> Option<&M::Measure> {
None
}
}
#[inline(always)]
fn measures_from_range<M: Measurable>(
range: &impl MeasureRange<M>,
limit: M::Measure,
) -> Result<(M::Measure, M::Measure), M> {
#[cfg(debug_assertions)]
{
if let Some(start) = range.start_bound() {
assert_default_is_lowest::<M>(start);
}
if let Some(end) = range.end_bound() {
assert_default_is_lowest::<M>(end);
}
}
match (range.start_bound(), range.end_bound()) {
(None, None) => Ok((M::Measure::default(), limit)),
(None, Some(end)) => {
if end.fallible_cmp(&limit).is_gt() {
Err(Error::MeasureRangeOutOfBounds(None, Some(*end), limit))
} else {
Ok((M::Measure::default(), *end))
}
}
(Some(start), None) => {
if start.fallible_cmp(&limit).is_gt() {
Err(Error::MeasureRangeOutOfBounds(Some(*start), None, limit))
} else {
Ok((*start, limit))
}
}
(Some(start), Some(end)) => {
if start.fallible_cmp(end).is_gt() {
Err(Error::MeasureRangeInvalid(Some(*start), Some(*end)))
} else if end.fallible_cmp(&limit).is_gt() || start.fallible_cmp(&limit).is_gt() {
Err(Error::MeasureRangeOutOfBounds(
Some(*start),
Some(*end),
limit,
))
} else {
Ok((*start, *end))
}
}
}
}
fn assert_default_is_lowest<M: Measurable>(cmp: &M::Measure) {
assert!(
M::Measure::default().fallible_cmp(cmp).is_le(),
"{:?} (Measure::default()) is supposed to be the smallest possible value for \
Measurable::Measure, and yet {:?} is smaller",
M::Measure::default(),
cmp
)
}
fn fallible_saturating_sub<T>(lhs: T, rhs: T) -> T
where
T: Default + FallibleOrd + Sub<Output = T>,
{
if lhs.fallible_cmp(&rhs).is_le() {
T::default()
} else {
lhs - rhs
}
}
fn fallible_min<T: FallibleOrd>(lhs: T, rhs: T) -> T {
if lhs.fallible_cmp(&rhs).is_le() {
lhs
} else {
rhs
}
}
fn fallible_max<T: FallibleOrd>(lhs: T, rhs: T) -> T {
if lhs.fallible_cmp(&rhs).is_ge() {
lhs
} else {
rhs
}
}