any_rope/
lib.rs

1#![allow(
2    incomplete_features,
3    clippy::arc_with_non_send_sync,
4    clippy::too_many_arguments
5)]
6#![feature(generic_const_exprs)]
7//! AnyRope is an arbitrary data rope for Rust.
8//!
9//! AnyRope's [`Rope<M>`] contains elements `M` that implement [`Measurable`], a
10//! trait that assigns an arbitrary "measure" to each element, through the
11//! [`measure()`][Measurable::measure] function. AnyRope can then use these
12//! "measures" to retrieve and iterate over elements in any given "measure" from
13//! the beginning of the [`Rope<M>`].
14//!
15//! Keep in mind that the "measure" does not correspond to the actual size of a
16//! type in bits or bytes, but is instead decided by the implementor, and can be
17//! whatever value they want.
18//!
19//! The library is made up of four main components:
20//!
21//! - [`Rope<M>`]: the main rope type.
22//! - [`RopeSlice<M>`]: an immutable view into part of a [`Rope<M>`].
23//! - [`iter`]: iterators over [`Rope<M>`]/[`RopeSlice<M>`] data.
24//! - [`RopeBuilder<M>`]: an efficient incremental [`Rope<M>`] builder.
25//!
26//! # A Basic Example
27//!
28//! Let's say we want create a tagging system that will be applied to text,
29//! in which the tags either tell you to print normally, print in red,
30//! underline, or skip:
31//!
32//! ```rust
33//! #![feature(generic_const_exprs)]
34//! # use std::io::Result;
35//! use std::fs::File;
36//! use std::io::{BufReader, BufWriter};
37//! use any_rope::{Rope, Measurable};
38//!
39//! // A simple tag structure that our program can understand.
40//! #[derive(Clone, Copy, PartialEq, Eq)]
41//! enum Tag {
42//!     InRed,
43//!     UnderLine,
44//!     Normal,
45//!     // The `usize` in here represents an amount of characters that won't change
46//!     // the color of the text.
47//!     Skip(usize)
48//! }
49//!
50//! impl Measurable for Tag {
51//!     type Measure = usize;
52//!
53//!     fn measure(&self) -> Self::Measure {
54//!         match self {
55//!             // The coloring tags are only meant to color, not to "move forward".
56//!             Tag::InRed | Tag::UnderLine | Tag::Normal => 0,
57//!             // The Skip tag represents an amount of characters in which no
58//!             // tags are applied.
59//!             Tag::Skip(amount) => *amount
60//!         }
61//!     }
62//! }
63//! use Tag::*;
64//!
65//! # fn activate_tag(tag: &Tag) {}
66//! // An `&str` that will be colored.
67//! let my_str = "This word will be red!";
68//!
69//! // Here's what this means:
70//! // - Skip 5 characters;
71//! // - Change the color to red;
72//! // - Start underlining;
73//! // - Skip 4 characters;
74//! // - Change the rendering back to normal.
75//! let my_tagger = Rope::from_slice(&[Skip(5), InRed, UnderLine, Skip(4), Normal]);
76//! // Do note that Tag::Skip only represents characters because we are also iterating
77//! // over a `Chars` iterator, and have chosen to do so.
78//!
79//! let mut tags_iter = my_tagger.iter().peekable();
80//! for (cur_index, ch) in my_str.chars().enumerate() {
81//!     // The while let loop here is a useful way to activate all tags within the same
82//!     // character. Note the sequence of [.., InRed, UnderLine, ..], both of which have
83//!     // a measure of 0. This means that both would be triggered before moving on to the next
84//!     // character.
85//!     while let Some((index, tag)) = tags_iter.peek() {
86//!         // The returned index is always the measure where an element began. In this
87//!         // case, `tags_iter.peek()` would return `Some((0, Skip(5)))`, and then
88//!         // `Some((5, InRed))`.
89//!         if *index == cur_index {
90//!             activate_tag(tag);
91//!             tags_iter.next();
92//!         } else {
93//!             break;
94//!         }
95//!     }
96//!
97//!     print!("{}", ch);
98//! }
99//! ```
100//!
101//! An example can be found in the `examples` directory, detailing a "search and
102//! replace" functionality for [`Rope<M>`].
103//!
104//! # Low-level APIs
105//!
106//! AnyRope also provides access to some of its low-level APIs, enabling client
107//! code to efficiently work with a [`Rope<M>`]'s data and implement new
108//! functionality.  The most important of those API's are:
109//!
110//! - The [`chunk_at_*()`][Rope::chunk_at_measure] chunk-fetching methods of
111//!   [`Rope<M>`] and [`RopeSlice<M>`].
112//! - The [`Chunks`](iter::Chunks) iterator.
113//! - The functions in `slice_utils` for operating on [`&[M]`][Measurable]
114//!   slices.
115//!
116//! As a reminder, if you notice similarities with the AnyRope crate, it is
117//! because this is a heavily modified fork of it.
118#![allow(
119    clippy::collapsible_if,
120    clippy::inline_always,
121    clippy::needless_return,
122    clippy::redundant_field_names,
123    clippy::type_complexity
124)]
125
126mod rope;
127mod rope_builder;
128mod slice;
129mod slice_utils;
130mod tree;
131
132pub mod iter;
133
134use std::{
135    cmp::Ordering,
136    fmt::Debug,
137    ops::{Add, Bound, Range, RangeFrom, RangeFull, RangeTo, Sub},
138};
139
140pub use crate::{
141    rope::Rope,
142    rope_builder::RopeBuilder,
143    slice::RopeSlice,
144    tree::{max_children, max_len},
145};
146
147/// A trait defining a comparison that must panic if there is ever ambiguity
148/// about the ordering in a given struct.
149pub trait FallibleOrd {
150    /// A comparison that can panic.
151    ///
152    /// This comparison should panic with the [`unreachable!`] macro, since the
153    /// panicking code is supposed to be unreachable from within `any-rope`.
154    ///
155    /// Here's an example of how this function should be implemented:
156    ///
157    /// ```rust
158    /// # use std::cmp::Ordering;
159    /// # use any_rope::FallibleOrd;
160    /// struct TwoUsizes(usize, usize);
161    ///
162    /// impl FallibleOrd for TwoUsizes {
163    ///     fn fallible_cmp(&self, other: &Self) -> Ordering {
164    ///         use Ordering::*;
165    ///         let cmp_0 = self.0.cmp(&other.0);
166    ///         let cmp_1 = self.1.cmp(&other.1);
167    ///
168    ///         match (cmp_0, cmp_1) {
169    ///             (Less, Less) => Less,
170    ///             (Less, Equal) => Less,
171    ///             (Equal, Less) => Less,
172    ///             (Equal, Equal) => Equal,
173    ///             (Equal, Greater) => Greater,
174    ///             (Greater, Equal) => Greater,
175    ///             (Greater, Greater) => todo!(),
176    ///             (Less, Greater) | (Greater, Less) => unreachable!(
177    ///                 "Ambiguous comparison, report this as a bug on the \
178    ///                  AnyRope crate"
179    ///             ),
180    ///         }
181    ///     }
182    /// }
183    /// ```
184    ///
185    /// Note that, if all values are equal, then the comparison is equal. If at
186    /// least one value is greater or lesse, then the comparison follows that
187    /// value. But if there are greater and lesser values at the same time, then
188    /// something has failed within `any-rope` itself, and that should be
189    /// reported as a bug.
190    fn fallible_cmp(&self, other: &Self) -> Ordering;
191}
192
193/// A object that has a user defined size, that can be interpreted by a
194/// [`Rope<M>`].
195pub trait Measurable: Clone {
196    /// This type is what will be used to query, iterate, modify, and slice up
197    /// the [`Rope`].
198    ///
199    /// It needs to be light, since it will be heavily utilized from within
200    /// `any-rope`, and needs to be malleable, such that it can be compared,
201    /// added and subtracted at will by the rope.
202    ///
203    /// Normally, in order to query, iterate, or modify the rope, the various
204    /// methods take in a comparator function. This function offers flexibility
205    /// in how one searches within the rope, for example:
206    ///
207    /// ```rust
208    /// # use std::{
209    /// #     cmp::Ordering,
210    /// #     ops::{Add, Sub},
211    /// # };
212    /// # use any_rope::{FallibleOrd, Measurable, Rope};
213    /// #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
214    /// struct TwoWidths(usize, usize);
215    ///
216    /// impl TwoWidths {
217    ///     fn first_cmp(&self, other: &Self) -> Ordering {
218    ///         self.0.cmp(&other.0)
219    ///     }
220    ///
221    ///     fn second_cmp(&self, other: &Self) -> Ordering {
222    ///         self.1.cmp(&other.1)
223    ///     }
224    /// }
225    ///
226    /// impl FallibleOrd for TwoWidths {
227    ///     fn fallible_cmp(&self, other: &Self) -> Ordering {
228    ///         use Ordering::*;
229    ///         let cmp_0 = self.0.cmp(&other.0);
230    ///         let cmp_1 = self.1.cmp(&other.1);
231    ///
232    ///         match (cmp_0, cmp_1) {
233    ///             (Less, Less) => Less,
234    ///             (Less, Equal) => Less,
235    ///             (Equal, Less) => Less,
236    ///             (Equal, Equal) => Equal,
237    ///             (Equal, Greater) => Greater,
238    ///             (Greater, Equal) => Greater,
239    ///             (Greater, Greater) => todo!(),
240    ///             (Less, Greater) | (Greater, Less) => unreachable!(
241    ///                 "Ambiguous comparison, report this as a bug on the \
242    ///                  AnyRope crate"
243    ///             ),
244    ///         }
245    ///     }
246    /// }
247    ///
248    /// // ... Implementation of `Add` and `Sub` for `TwoWidths`.
249    ///
250    /// # impl Add for TwoWidths {
251    /// #     type Output = Self;
252    ///
253    /// #     fn add(self, other: Self) -> Self::Output {
254    /// #         Self(self.0 + other.0, self.1 + other.1)
255    /// #     }
256    /// # }
257    /// # impl Sub for TwoWidths {
258    /// #     type Output = Self;
259    ///
260    /// #     fn sub(self, other: Self) -> Self::Output {
261    /// #         Self(self.0 - other.0, self.1 - other.1)
262    /// #     }
263    /// # }
264    /// #[derive(Clone, Copy, PartialEq, Eq)]
265    /// struct MyStruct(TwoWidths);
266    ///
267    /// impl Measurable for MyStruct {
268    ///     type Measure = TwoWidths;
269    ///
270    ///     fn measure(&self) -> Self::Measure {
271    ///         self.0
272    ///     }
273    /// }
274    /// ```
275    ///
276    /// With the `TwoWidths::first_cmp` and `TwoWidths::second_cmp`, you can
277    /// search with two different variables within the rope, similarly to how
278    /// regular ropes let you search by byte, char, or line.
279    ///
280    /// Note, however, that this type also requires `PartialOrd` and `Ord`. That
281    /// is because, internally, `any-rope` needs those comparison functions to
282    /// sort itself out. These implementations also cannot be derived by Rust,
283    /// and need to be
284    type Measure: Debug
285        + Default
286        + Clone
287        + Copy
288        + PartialEq
289        + Eq
290        + Add<Output = Self::Measure>
291        + Sub<Output = Self::Measure>
292        + FallibleOrd;
293
294    /// The measure of this element, it need not be the actual lenght in bytes,
295    /// but just a representative value, to be fed to the [`Rope<M>`].
296    fn measure(&self) -> Self::Measure;
297}
298
299/// A struct meant for testing and exemplification
300///
301/// Its [`measure`][Measurable::measure] is always equal to the number within.
302#[derive(Debug, Clone, Copy, PartialEq, Eq)]
303pub struct Width(pub usize);
304
305impl PartialOrd for Width {
306    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
307        Some(self.cmp(other))
308    }
309}
310
311impl Ord for Width {
312    fn cmp(&self, other: &Self) -> Ordering {
313        self.0.fallible_cmp(&other.0)
314    }
315}
316
317impl FallibleOrd for usize {
318    fn fallible_cmp(&self, other: &Self) -> Ordering {
319        self.cmp(other)
320    }
321}
322
323impl Measurable for Width {
324    type Measure = usize;
325
326    fn measure(&self) -> Self::Measure {
327        self.0
328    }
329}
330
331//==============================================================
332// Error reporting types.
333
334/// AnyRope's result type.
335pub type Result<T, M> = std::result::Result<T, Error<M>>;
336
337/// AnyRope's error type.
338#[derive(Clone, Copy)]
339#[non_exhaustive]
340pub enum Error<M: Measurable> {
341    /// Indicates that the passed index was out of bounds.
342    ///
343    /// Contains the index attempted and the actual length of the
344    /// [`Rope<M>`]/[`RopeSlice<M>`], in that order.
345    IndexOutOfBounds(usize, usize),
346
347    /// Indicates that the passed measure was out of bounds.
348    ///
349    /// Contains the index attempted and the actual measure of the
350    /// [`Rope<M>`]/[`RopeSlice<M>`], in that order.
351    MeasureOutOfBounds(M::Measure, M::Measure),
352
353    /// Indicates that a reversed index range (end < start) was encountered.
354    ///
355    /// Contains the [start, end) indices of the range, in that order.
356    IndexRangeInvalid(usize, usize),
357
358    /// Indicates that a reversed measure range (end < start) was
359    /// encountered.
360    ///
361    /// Contains the [start, end) measures of the range, in that order.
362    MeasureRangeInvalid(Option<M::Measure>, Option<M::Measure>),
363
364    /// Indicates that the passed index range was partially or fully out of
365    /// bounds.
366    ///
367    /// Contains the [start, end) indices of the range and the actual
368    /// length of the [`Rope<M>`]/[`RopeSlice<M>`], in that order.
369    /// When either the start or end are [`None`], that indicates a half-open
370    /// range.
371    IndexRangeOutOfBounds(Option<usize>, Option<usize>, usize),
372
373    /// Indicates that the passed measure range was partially or fully out of
374    /// bounds.
375    ///
376    /// Contains the [start, end) measures of the range and the actual
377    /// measure of the [`Rope<M>`]/[`RopeSlice<M>`], in that order.
378    /// When either the start or end are [`None`], that indicates a half-open
379    /// range.
380    MeasureRangeOutOfBounds(Option<M::Measure>, Option<M::Measure>, M::Measure),
381}
382
383impl<M: Measurable> std::fmt::Debug for Error<M> {
384    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
385        match *self {
386            Error::IndexOutOfBounds(index, len) => {
387                write!(
388                    f,
389                    "Index out of bounds: index {}, Rope/RopeSlice length {}",
390                    index, len
391                )
392            }
393            Error::MeasureOutOfBounds(measure, max) => {
394                write!(
395                    f,
396                    "Measure out of bounds: measure {:?}, Rope/RopeSlice measure {:?}",
397                    measure, max
398                )
399            }
400            Error::IndexRangeInvalid(start_index, end_index) => {
401                write!(
402                    f,
403                    "Invalid index range {}..{}: start must be <= end",
404                    start_index, end_index
405                )
406            }
407            Error::MeasureRangeInvalid(start_measure, end_measure) => {
408                write!(
409                    f,
410                    "Invalid measure range {:?}..{:?}: start must be <= end",
411                    start_measure, end_measure
412                )
413            }
414            Error::IndexRangeOutOfBounds(start, end, len) => {
415                write!(f, "Index range out of bounds: index range ")?;
416                write_range(f, start, end)?;
417                write!(f, ", Rope/RopeSlice byte length {}", len)
418            }
419            Error::MeasureRangeOutOfBounds(start, end, measure) => {
420                write!(f, "Measure range out of bounds: measure range ")?;
421                write_range(f, start, end)?;
422                write!(f, ", Rope/RopeSlice measure {:?}", measure)
423            }
424        }
425    }
426}
427
428impl<M: Measurable> std::error::Error for Error<M> {}
429
430impl<M: Measurable> std::fmt::Display for Error<M> {
431    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
432        // Just re-use the debug impl.
433        std::fmt::Debug::fmt(self, f)
434    }
435}
436
437fn write_range<T: Debug>(
438    f: &mut std::fmt::Formatter<'_>,
439    start_idx: Option<T>,
440    end_idx: Option<T>,
441) -> std::fmt::Result {
442    match (start_idx, end_idx) {
443        (None, None) => write!(f, ".."),
444        (None, Some(end)) => write!(f, "..{:?}", end),
445        (Some(start), None) => write!(f, "{:?}..", start),
446        (Some(start), Some(end)) => write!(f, "{:?}..{:?}", start, end),
447    }
448}
449
450//==============================================================
451// Range handling utilities.
452
453#[inline(always)]
454fn start_bound_to_num(b: Bound<&usize>) -> Option<usize> {
455    match b {
456        Bound::Included(n) => Some(*n),
457        Bound::Excluded(n) => Some(*n + 1),
458        Bound::Unbounded => None,
459    }
460}
461
462#[inline(always)]
463fn end_bound_to_num(b: Bound<&usize>) -> Option<usize> {
464    match b {
465        Bound::Included(n) => Some(*n + 1),
466        Bound::Excluded(n) => Some(*n),
467        Bound::Unbounded => None,
468    }
469}
470
471mod hidden {
472    use std::ops::{Range, RangeFrom, RangeFull, RangeTo};
473
474    pub trait Internal {}
475
476    impl<T> Internal for Range<T> {}
477    impl<T> Internal for RangeFrom<T> {}
478    impl<T> Internal for RangeTo<T> {}
479    impl Internal for RangeFull {}
480}
481
482pub trait MeasureRange<M: Measurable>: hidden::Internal {
483    fn start_bound(&self) -> Option<&M::Measure>;
484
485    fn end_bound(&self) -> Option<&M::Measure>;
486}
487
488impl<M: Measurable> MeasureRange<M> for Range<M::Measure> {
489    fn start_bound(&self) -> Option<&M::Measure> {
490        Some(&self.start)
491    }
492
493    fn end_bound(&self) -> Option<&M::Measure> {
494        Some(&self.end)
495    }
496}
497
498impl<M: Measurable> MeasureRange<M> for RangeFrom<M::Measure> {
499    fn start_bound(&self) -> Option<&M::Measure> {
500        Some(&self.start)
501    }
502
503    fn end_bound(&self) -> Option<&M::Measure> {
504        None
505    }
506}
507
508impl<M: Measurable> MeasureRange<M> for RangeTo<M::Measure> {
509    fn start_bound(&self) -> Option<&M::Measure> {
510        None
511    }
512
513    fn end_bound(&self) -> Option<&M::Measure> {
514        Some(&self.end)
515    }
516}
517
518impl<M: Measurable> MeasureRange<M> for RangeFull {
519    fn start_bound(&self) -> Option<&M::Measure> {
520        None
521    }
522
523    fn end_bound(&self) -> Option<&M::Measure> {
524        None
525    }
526}
527
528#[inline(always)]
529fn measures_from_range<M: Measurable>(
530    range: &impl MeasureRange<M>,
531    limit: M::Measure,
532) -> Result<(M::Measure, M::Measure), M> {
533    #[cfg(debug_assertions)]
534    {
535        if let Some(start) = range.start_bound() {
536            assert_default_is_lowest::<M>(start);
537        }
538        if let Some(end) = range.end_bound() {
539            assert_default_is_lowest::<M>(end);
540        }
541    }
542
543    match (range.start_bound(), range.end_bound()) {
544        (None, None) => Ok((M::Measure::default(), limit)),
545        (None, Some(end)) => {
546            if end.fallible_cmp(&limit).is_gt() {
547                Err(Error::MeasureRangeOutOfBounds(None, Some(*end), limit))
548            } else {
549                Ok((M::Measure::default(), *end))
550            }
551        }
552        (Some(start), None) => {
553            if start.fallible_cmp(&limit).is_gt() {
554                Err(Error::MeasureRangeOutOfBounds(Some(*start), None, limit))
555            } else {
556                Ok((*start, limit))
557            }
558        }
559
560        (Some(start), Some(end)) => {
561            if start.fallible_cmp(end).is_gt() {
562                Err(Error::MeasureRangeInvalid(Some(*start), Some(*end)))
563            } else if end.fallible_cmp(&limit).is_gt() || start.fallible_cmp(&limit).is_gt() {
564                Err(Error::MeasureRangeOutOfBounds(
565                    Some(*start),
566                    Some(*end),
567                    limit,
568                ))
569            } else {
570                Ok((*start, *end))
571            }
572        }
573    }
574}
575
576//==============================================================
577// Other utilities.
578
579fn assert_default_is_lowest<M: Measurable>(cmp: &M::Measure) {
580    assert!(
581        M::Measure::default().fallible_cmp(cmp).is_le(),
582        "{:?} (Measure::default()) is supposed to be the smallest possible value for \
583         Measurable::Measure, and yet {:?} is smaller",
584        M::Measure::default(),
585        cmp
586    )
587}
588
589fn fallible_saturating_sub<T>(lhs: T, rhs: T) -> T
590where
591    T: Default + FallibleOrd + Sub<Output = T>,
592{
593    if lhs.fallible_cmp(&rhs).is_le() {
594        T::default()
595    } else {
596        lhs - rhs
597    }
598}
599
600fn fallible_min<T: FallibleOrd>(lhs: T, rhs: T) -> T {
601    if lhs.fallible_cmp(&rhs).is_le() {
602        lhs
603    } else {
604        rhs
605    }
606}
607
608fn fallible_max<T: FallibleOrd>(lhs: T, rhs: T) -> T {
609    if lhs.fallible_cmp(&rhs).is_ge() {
610        lhs
611    } else {
612        rhs
613    }
614}