any_rope/
slice.rs

1use std::{cmp::Ordering, ops::RangeBounds, sync::Arc};
2
3use crate::{
4    end_bound_to_num, fallible_saturating_sub,
5    iter::{Chunks, Iter},
6    measures_from_range,
7    rope::Rope,
8    slice_utils::{end_measure_to_index, index_to_measure, measure_of, start_measure_to_index},
9    start_bound_to_num,
10    tree::{max_children, max_len, Count, Node, SliceInfo},
11    Error, FallibleOrd, Measurable, MeasureRange, Result,
12};
13
14/// An immutable view into part of a [`Rope<M>`].
15///
16/// Just like standard [`&[M]`][Measurable] slices, [`RopeSlice<M>`]s behave as
17/// if the slice in their range is the only slice that exists. All indexing is
18/// relative to the start of their range, and all iterators and methods that
19/// return [`M`][Measurable]s truncate those to the range of the slice.
20///
21/// In other words, the behavior of a [`RopeSlice<M>`] is always identical to
22/// that of a full [`Rope<M>`] created from the same slice range. Nothing should
23/// be surprising here.
24#[derive(Copy, Clone)]
25pub struct RopeSlice<'a, M>(pub(crate) RSEnum<'a, M>)
26where
27    M: Measurable,
28    [(); max_len::<M, M::Measure>()]: Sized,
29    [(); max_children::<M, M::Measure>()]: Sized;
30
31#[derive(Copy, Clone, Debug)]
32pub(crate) enum RSEnum<'a, M>
33where
34    M: Measurable,
35    [(); max_len::<M, M::Measure>()]: Sized,
36    [(); max_children::<M, M::Measure>()]: Sized,
37{
38    Full {
39        node: &'a Arc<Node<M>>,
40        start_info: SliceInfo<M::Measure>,
41        end_info: SliceInfo<M::Measure>,
42    },
43    Light {
44        slice: &'a [M],
45    },
46}
47
48impl<'a, M> RopeSlice<'a, M>
49where
50    M: Measurable,
51    [(); max_len::<M, M::Measure>()]: Sized,
52    [(); max_children::<M, M::Measure>()]: Sized,
53{
54    pub(crate) fn new_with_range(
55        node: &'a Arc<Node<M>>,
56        start: M::Measure,
57        end: M::Measure,
58        cmp: &impl Fn(&M::Measure, &M::Measure) -> Ordering,
59    ) -> Self {
60        // Early-out shortcut for taking a slice of the full thing.
61        if cmp(&start, &M::Measure::default()).is_eq() && cmp(&end, &node.measure()).is_eq() {
62            if node.is_leaf() {
63                let slice = node.leaf_slice();
64                return RopeSlice(RSEnum::Light { slice });
65            } else {
66                return RopeSlice(RSEnum::Full {
67                    node,
68                    start_info: SliceInfo {
69                        len: 0,
70                        measure: M::Measure::default(),
71                    },
72                    end_info: SliceInfo {
73                        len: node.len() as Count,
74                        measure: node.measure(),
75                    },
76                });
77            }
78        }
79
80        // Find the deepest node that still contains the full range given.
81        let mut n_start = start;
82        let mut n_end = end;
83        let mut node = node;
84        'outer: loop {
85            match *(node as &Node<M>) {
86                // Early out if we reach a leaf, because we can do the
87                // simpler lightweight slice then.
88                Node::Leaf(ref slice) => {
89                    let start = start_measure_to_index(slice, n_start, cmp);
90                    let end = start + end_measure_to_index(&slice[start..], n_end - n_start, cmp);
91                    return RopeSlice(RSEnum::Light {
92                        slice: &slice[start..end],
93                    });
94                }
95
96                Node::Branch(ref children) => {
97                    let mut start_measure = M::Measure::default();
98                    for (i, info) in children.info().iter().enumerate() {
99                        if cmp(&n_start, &start_measure).is_gt()
100                            && cmp(&n_end, &(start_measure + info.measure)).is_lt()
101                        {
102                            n_start = n_start - start_measure;
103                            n_end = n_end - start_measure;
104                            node = &children.nodes()[i];
105                            continue 'outer;
106                        }
107                        start_measure = start_measure + info.measure;
108                    }
109                    break;
110                }
111            }
112        }
113
114        // Create the slice
115        RopeSlice(RSEnum::Full {
116            node,
117            start_info: node.start_measure_to_slice_info(n_start, cmp),
118            end_info: node.end_measure_to_slice_info(n_end, cmp),
119        })
120    }
121
122    pub(crate) fn new_with_index_range(
123        node: &'a Arc<Node<M>>,
124        start: usize,
125        end: usize,
126    ) -> Result<Self, M> {
127        assert!(start <= end);
128        assert!(end <= node.info().len as usize);
129
130        // Early-out shortcut for taking a slice of the full thing.
131        if start == 0 && end == node.len() {
132            if node.is_leaf() {
133                let slice = node.leaf_slice();
134                return Ok(RopeSlice(RSEnum::Light { slice }));
135            } else {
136                return Ok(RopeSlice(RSEnum::Full {
137                    node,
138                    start_info: SliceInfo {
139                        len: 0,
140                        measure: M::Measure::default(),
141                    },
142                    end_info: SliceInfo {
143                        len: node.len() as Count,
144                        measure: node.measure(),
145                    },
146                }));
147            }
148        }
149
150        // Find the deepest node that still contains the full range given.
151        let mut n_start = start;
152        let mut n_end = end;
153        let mut node = node;
154        'outer: loop {
155            match *(node as &Node<M>) {
156                // Early out if we reach a leaf, because we can do the
157                // simpler lightweight slice then.
158                Node::Leaf(ref slice) => {
159                    let start_index = n_start;
160                    let end_index = n_end;
161                    return Ok(RopeSlice(RSEnum::Light {
162                        slice: &slice[start_index..end_index],
163                    }));
164                }
165
166                Node::Branch(ref children) => {
167                    let mut start_index = 0;
168                    for (i, info) in children.info().iter().enumerate() {
169                        if n_start >= start_index && n_end <= (start_index + info.len as usize) {
170                            n_start -= start_index;
171                            n_end -= start_index;
172                            node = &children.nodes()[i];
173                            continue 'outer;
174                        }
175                        start_index += info.len as usize;
176                    }
177                    break;
178                }
179            }
180        }
181
182        // Create the slice
183        Ok(RopeSlice(RSEnum::Full {
184            node,
185            start_info: node.index_to_slice_info(n_start),
186            end_info: node.index_to_slice_info(n_end),
187        }))
188    }
189
190    //-----------------------------------------------------------------------
191    // Informational methods
192
193    /// Total number of elements in [`RopeSlice<M>`].
194    ///
195    /// Runs in O(1) time.
196    #[inline]
197    pub fn len(&self) -> usize {
198        match *self {
199            RopeSlice(RSEnum::Full {
200                end_info,
201                start_info,
202                ..
203            }) => (end_info.len - start_info.len) as usize,
204            RopeSlice(RSEnum::Light { slice }) => slice.len(),
205        }
206    }
207
208    /// Returns `true` if the [`RopeSlice<M>`] is empty.
209    ///
210    /// Runs in O(1) time.
211    #[inline]
212    pub fn is_empty(&self) -> bool {
213        self.len() == 0
214    }
215
216    /// Sum of all measures of in [`RopeSlice<M>`].
217    ///
218    /// Runs in O(1) time.
219    #[inline]
220    pub fn measure(&self) -> M::Measure {
221        match *self {
222            RopeSlice(RSEnum::Full {
223                end_info,
224                start_info,
225                ..
226            }) => end_info.measure - start_info.measure,
227            RopeSlice(RSEnum::Light { slice }) => measure_of(slice),
228        }
229    }
230
231    //-----------------------------------------------------------------------
232    // Index conversion methods
233
234    /// Returns the measure sum at the start of the given index.
235    ///
236    /// Notes:
237    ///
238    /// Runs in O(log N) time.
239    ///
240    /// # Panics
241    ///
242    /// Panics if the `index` is out of bounds (i.e. `index > Rope::len()`).
243    #[inline]
244    pub fn index_to_measure(&self, index: usize) -> M::Measure {
245        self.try_index_to_measure(index).unwrap()
246    }
247
248    /// Returns an index, given a starting measure sum.
249    ///
250    /// Runs in O(log N) time.
251    ///
252    /// # Panics
253    ///
254    /// Panics if the `measure` is out of bounds (i.e. `measure >
255    /// RopeSlice::measure()`).
256    #[inline]
257    pub fn start_measure_to_index(
258        &self,
259        measure: M::Measure,
260        cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering,
261    ) -> usize {
262        self.try_start_measure_to_index(measure, cmp).unwrap()
263    }
264
265    /// Returns an index, given an ending measure sum.
266    ///
267    /// Runs in O(log N) time.
268    ///
269    /// # Panics
270    ///
271    /// Panics if the `measure` is out of bounds (i.e. `measure >
272    /// RopeSlice::measure()`).
273    #[inline]
274    pub fn end_measure_to_index(
275        &self,
276        measure: M::Measure,
277        cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering,
278    ) -> usize {
279        self.try_end_measure_to_index(measure, cmp).unwrap()
280    }
281
282    //-----------------------------------------------------------------------
283    // Fetch methods
284
285    /// Returns the [`M`][Measurable] at `index` and the starting measure sum of
286    /// that element.
287    ///
288    /// Runs in O(log N) time.
289    ///
290    /// # Panics
291    ///
292    /// Panics if the `index` is out of bounds (i.e. `index >
293    /// RopeSlice::len()`).
294    #[inline]
295    pub fn from_index(&self, index: usize) -> (M::Measure, M) {
296        // Bounds check
297        if let Some(out) = self.get_from_index(index) {
298            out
299        } else {
300            panic!(
301                "Attempt to index past end of slice: index {}, slice length {}",
302                index,
303                self.len()
304            );
305        }
306    }
307
308    /// Returns the [`M`][Measurable] at `measure` and the starting measure sum
309    /// of that element.
310    ///
311    /// Runs in O(log N) time.
312    ///
313    /// # Panics
314    ///
315    /// Panics if the `measure` is out of bounds (i.e. `measure >
316    /// RopeSlice::measure()`).
317    #[inline]
318    pub fn from_measure(
319        &self,
320        measure: M::Measure,
321        cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering,
322    ) -> (M::Measure, M) {
323        if let Some(out) = self.get_from_measure(measure, cmp) {
324            out
325        } else {
326            panic!(
327                "Attempt to index past end of slice: measure {:?}, slice measure {:?}",
328                measure,
329                self.measure()
330            );
331        }
332    }
333
334    /// Returns the chunk containing the given index.
335    ///
336    /// Also returns the index and measure of the beginning of the chunk.
337    ///
338    /// Note: for convenience, a one-past-the-end `index` returns the last
339    /// chunk of the [`RopeSlice<M>`].
340    ///
341    /// The return value is organized as `(chunk, chunk_index, chunk_measure)`.
342    ///
343    /// Runs in O(log N) time.
344    ///
345    /// # Panics
346    ///
347    /// Panics if the `index` is out of bounds (i.e. `index >
348    /// RopeSlice::len()`).
349    #[inline]
350    pub fn chunk_at_index(&self, index: usize) -> (&'a [M], usize, M::Measure) {
351        self.try_chunk_at_index(index).unwrap()
352    }
353
354    /// Returns the chunk containing the given measure.
355    ///
356    /// Also returns the index and measure of the beginning of the chunk.
357    ///
358    /// Note: for convenience, a one-past-the-end `measure` returns the last
359    /// chunk of the [`RopeSlice<M>`].
360    ///
361    /// The return value is organized as `(chunk, chunk_index, chunk_measure)`.
362    ///
363    /// Runs in O(log N) time.
364    ///
365    /// # Panics
366    ///
367    /// Panics if `measure` is out of bounds (i.e. `measure >
368    /// RopeSlice::measure()`).
369    #[inline]
370    pub fn chunk_at_measure(
371        &self,
372        measure: M::Measure,
373        cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering,
374    ) -> (&'a [M], usize, M::Measure) {
375        if let Some(out) = self.get_chunk_at_measure(measure, cmp) {
376            out
377        } else {
378            panic!(
379                "Attempt to index past end of slice: measure {:?}, slice measure {:?}",
380                measure,
381                self.measure()
382            );
383        }
384    }
385
386    /// Returns the entire contents of the [`RopeSlice<M>`] as a
387    /// [`&[M]`][Measurable] if possible.
388    ///
389    /// This is useful for optimizing cases where the [`RopeSlice<M>`] is not
390    /// very long.
391    ///
392    /// For large slices this method will typically fail and return [`None`]
393    /// because large slices usually cross chunk boundaries in the rope.
394    ///
395    /// (Also see the [`From`] impl for converting to a
396    /// [`Cow<&[M]>`][std::borrow::Cow].)
397    ///
398    /// Runs in O(1) time.
399    #[inline]
400    pub fn as_slice(&self) -> Option<&'a [M]> {
401        match *self {
402            RopeSlice(RSEnum::Full { .. }) => None,
403            RopeSlice(RSEnum::Light { slice }) => Some(slice),
404        }
405    }
406
407    //-----------------------------------------------------------------------
408    // Slice creation
409
410    /// Gets an sub-slice of the [`RopeSlice<M>`], using a measure range.
411    ///
412    /// Uses range syntax, e.g. `2..7`, `2..`, etc.
413    ///
414    /// # Example
415    ///
416    /// ```rust
417    /// # use any_rope::Rope;
418    /// # use any_rope::Width;
419    /// let mut rope = Rope::from_slice(&[
420    ///     Width(1),
421    ///     Width(2),
422    ///     Width(3),
423    ///     Width(0),
424    ///     Width(0),
425    ///     Width(2),
426    ///     Width(1),
427    /// ]);
428    /// let slice = rope.measure_slice(..5, usize::cmp);
429    ///
430    /// assert_eq!(slice, [Width(1), Width(2), Width(3)].as_slice());
431    /// ```
432    ///
433    /// Runs in O(log N) time.
434    ///
435    /// # Panics
436    ///
437    /// Panics if the start of the range is greater than the end, or if the
438    /// end is out of bounds (i.e. `end > RopeSlice::measure()`).
439    #[inline]
440    pub fn measure_slice(
441        &self,
442        range: impl MeasureRange<M>,
443        cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering,
444    ) -> Self {
445        let (start, end) = measures_from_range(&range, self.measure()).unwrap();
446
447        if cmp(&start, &M::Measure::default()).is_eq() && cmp(&end, &self.measure()).is_eq() {
448            return self.clone();
449        }
450
451        match *self {
452            RopeSlice(RSEnum::Full { node, .. }) => {
453                RopeSlice::new_with_range(node, start, end, &cmp)
454            }
455            RopeSlice(RSEnum::Light { slice, .. }) => {
456                let start_index = start_measure_to_index(slice, start, &cmp);
457                let end_index = end_measure_to_index(slice, end, cmp);
458                let new_slice = &slice[start_index..end_index];
459                RopeSlice(RSEnum::Light { slice: new_slice })
460            }
461        }
462    }
463
464    /// Gets and sub-slice of the [`RopeSlice<M>`], using an index range.
465    ///
466    /// Uses range syntax, e.g. `2..7`, `2..`, etc.
467    ///
468    /// Runs in O(log N) time.
469    ///
470    /// # Panics
471    ///
472    /// Panics if:
473    /// - The start of the range is greater than the end.
474    /// - The end is out of bounds (i.e. `end > Rope::len()`).
475    #[inline]
476    pub fn index_slice<R>(&self, index_range: R) -> Self
477    where
478        R: RangeBounds<usize>,
479    {
480        match self.get_slice_impl(index_range) {
481            Ok(s) => return s,
482            Err(e) => panic!("slice(): {}", e),
483        }
484    }
485
486    //-----------------------------------------------------------------------
487    // Iterator methods
488
489    /// Creates an iterator over the [`RopeSlice<M>`].
490    ///
491    /// This iterator will return values of type [`Option<(usize, M)>`], where
492    /// the `usize` is the measure sum where the given [`M`][Measurable]
493    /// starts.
494    ///
495    /// Runs in O(log N) time.
496    #[inline]
497    pub fn iter(&self) -> Iter<'a, M> {
498        match *self {
499            RopeSlice(RSEnum::Full {
500                node,
501                start_info,
502                end_info,
503            }) => Iter::new_with_range(
504                node,
505                (start_info.len as usize, end_info.len as usize),
506                (start_info.measure, end_info.measure),
507                M::Measure::fallible_cmp,
508            ),
509            RopeSlice(RSEnum::Light { slice, .. }) => Iter::from_slice(slice),
510        }
511    }
512
513    /// Creates an iterator over the [`RopeSlice<M>`], starting at `measure`.
514    ///
515    /// This iterator will return values of type [`Option<(usize, M)>`], where
516    /// the `usize` is the measure where the given [`M`][Measurable] starts.
517    /// Since one can iterate in between an [`M`][Measurable]s start and end
518    /// measure sums. the first `usize` may not actually corelate to the
519    /// `measure` given to the function.
520    ///
521    /// If `measure == RopeSlice::measure()` then an iterator at the end of the
522    /// [`RopeSlice<M>`] is created (i.e. [`next()`][crate::iter::Iter::next]
523    /// will return [`None`]).
524    ///
525    /// Runs in O(log N) time.
526    ///
527    /// # Panics
528    ///
529    /// Panics if the `measure` is out of bounds (i.e. `measure >
530    /// RopeSlice::measure()`).
531    #[inline]
532    pub fn iter_at(
533        &self,
534        measure: M::Measure,
535        cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering,
536    ) -> Iter<'a, M> {
537        if let Some(out) = self.get_iter_at(measure, cmp) {
538            out
539        } else {
540            panic!(
541                "Attempt to index past end of RopeSlice: measure {:?}, RopeSlice measure {:?}",
542                measure,
543                self.measure()
544            );
545        }
546    }
547
548    /// Creates an iterator over the chunks of the [`RopeSlice<M>`].
549    ///
550    /// Runs in O(log N) time.
551    #[inline]
552    pub fn chunks(&self) -> Chunks<'a, M> {
553        match *self {
554            RopeSlice(RSEnum::Full {
555                node,
556                start_info,
557                end_info,
558            }) => Chunks::new_with_range(
559                node,
560                (start_info.len as usize, end_info.len as usize),
561                (start_info.measure, end_info.measure),
562            ),
563            RopeSlice(RSEnum::Light { slice, .. }) => Chunks::from_slice(slice, false),
564        }
565    }
566
567    /// Creates an iterator over the chunks of the [`RopeSlice<M>`], with the
568    /// iterator starting at the chunk containing the `index`.
569    ///
570    /// Also returns the index and measure of the beginning of the first
571    /// chunk to be yielded.
572    ///
573    /// If `index == RopeSlice::len()` an iterator at the end of the
574    /// [`RopeSlice<M>`] (yielding [`None`] on a call to
575    /// [`next()`][crate::iter::Iter::next]) is created.
576    ///
577    /// The return value is organized as `(iterator, chunk_index,
578    /// chunk_measure)`.
579    ///
580    /// Runs in O(log N) time.
581    ///
582    /// # Panics
583    ///
584    /// Panics if the `index` is out of bounds (i.e. `index >
585    /// RopeSlice::len()`).
586    #[inline]
587    pub fn chunks_at_index(&self, index: usize) -> (Chunks<'a, M>, usize, M::Measure) {
588        if let Some(out) = self.get_chunks_at_index(index) {
589            out
590        } else {
591            panic!(
592                "Attempt to index past end of RopeSlice: index {}, RopeSlice length {}",
593                index,
594                self.len()
595            );
596        }
597    }
598
599    /// Creates an iterator over the chunks of the [`RopeSlice<M>`], with the
600    /// iterator starting at the chunk containing the `measure`.
601    ///
602    /// Also returns the index and measure of the beginning of the first
603    /// chunk to be yielded.
604    ///
605    /// If `measure == RopeSlice::measure()` an iterator at the end of the
606    /// [`RopeSlice<M>`] (yielding [`None`] on a call to
607    /// [`next()`][crate::iter::Iter::next]) is created.
608    ///
609    /// The return value is organized as `(iterator, chunk_index,
610    /// chunk_measure)`.
611    ///
612    /// Runs in O(log N) time.
613    ///
614    /// # Panics
615    ///
616    /// Panics if the `measure` is out of bounds (i.e. `measure >
617    /// RopeSlice::measure()`).
618    #[inline]
619    pub fn chunks_at_measure(
620        &self,
621        measure: M::Measure,
622        cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering,
623    ) -> (Chunks<'a, M>, usize, M::Measure) {
624        if let Some(out) = self.get_chunks_at_measure(measure, cmp) {
625            out
626        } else {
627            panic!(
628                "Attempt to index past end of RopeSlice: measure {:?}, RopeSlice measure {:?}",
629                measure,
630                self.measure()
631            );
632        }
633    }
634}
635
636/// # Non-Panicking
637///
638/// The methods in this impl block provide non-panicking versions of
639/// [`RopeSlice<M>`]'s panicking methods. They return either `Option::None` or
640/// `Result::Err()` when their panicking counterparts would have panicked.
641impl<'a, M> RopeSlice<'a, M>
642where
643    M: Measurable,
644    [(); max_len::<M, M::Measure>()]: Sized,
645    [(); max_children::<M, M::Measure>()]: Sized,
646{
647    /// Non-panicking version of
648    /// [`index_to_measure()`][RopeSlice::index_to_measure].
649    #[inline]
650    pub fn try_index_to_measure(&self, index: usize) -> Result<M::Measure, M> {
651        // Bounds check
652        if index <= self.len() {
653            let (chunk, b, c) = self.chunk_at_index(index);
654            Ok(c + index_to_measure(chunk, index - b))
655        } else {
656            Err(Error::IndexOutOfBounds(index, self.len()))
657        }
658    }
659
660    /// Non-panicking version of
661    /// [`start_measure_to_index()`][RopeSlice::start_measure_to_index].
662    #[inline]
663    pub fn try_start_measure_to_index(
664        &self,
665        measure: M::Measure,
666        cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering,
667    ) -> Result<usize, M> {
668        // Bounds check
669        if cmp(&measure, &self.measure()).is_le() {
670            let (chunk, b, c) = self.chunk_at_measure(measure, &cmp);
671            Ok(b + start_measure_to_index(chunk, measure - c, cmp))
672        } else {
673            Err(Error::MeasureOutOfBounds(measure, self.measure()))
674        }
675    }
676
677    /// Non-panicking version of
678    /// [`end_measure_to_index()`][RopeSlice::end_measure_to_index].
679    #[inline]
680    pub fn try_end_measure_to_index(
681        &self,
682        measure: M::Measure,
683        cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering,
684    ) -> Result<usize, M> {
685        // Bounds check
686        if cmp(&measure, &self.measure()).is_le() {
687            let (chunk, b, c) = self.chunk_at_measure(measure, &cmp);
688            Ok(b + end_measure_to_index(chunk, measure - c, cmp))
689        } else {
690            Err(Error::MeasureOutOfBounds(measure, self.measure()))
691        }
692    }
693
694    /// Non-panicking version of [`from_index()`][RopeSlice::from_index].
695    #[inline]
696    pub fn get_from_index(&self, index: usize) -> Option<(M::Measure, M)> {
697        // Bounds check
698        if index < self.len() {
699            let (chunk, chunk_index, chunk_measure) = self.chunk_at_index(index);
700            let chunk_rel_index = index - chunk_index;
701            let measure = index_to_measure(chunk, chunk_rel_index);
702            Some((measure + chunk_measure, chunk[chunk_rel_index].clone()))
703        } else {
704            None
705        }
706    }
707
708    /// Non-panicking version of [`from_measure()`][RopeSlice::from_measure].
709    #[inline]
710    pub fn get_from_measure(
711        &self,
712        measure: M::Measure,
713        cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering,
714    ) -> Option<(M::Measure, M)> {
715        // Bounds check
716        if cmp(&measure, &self.measure()).is_lt() {
717            let (chunk, _, chunk_measure) = self.chunk_at_measure(measure, &cmp);
718            let index = start_measure_to_index(chunk, measure - chunk_measure, cmp);
719            let measure = index_to_measure(chunk, index);
720            Some((measure + chunk_measure, chunk[index].clone()))
721        } else {
722            None
723        }
724    }
725
726    /// Non-panicking version of
727    /// [`chunk_at_index()`][RopeSlice::chunk_at_index].
728    #[inline]
729    pub fn try_chunk_at_index(&self, index: usize) -> Result<(&'a [M], usize, M::Measure), M> {
730        // Bounds check
731        if index <= self.len() {
732            match *self {
733                RopeSlice(RSEnum::Full {
734                    node,
735                    start_info,
736                    end_info,
737                }) => {
738                    // Get the chunk.
739                    let (chunk, chunk_start_info) =
740                        node.get_chunk_at_index(index + start_info.len as usize);
741
742                    // Calculate clipped start/end indices within the chunk.
743                    let chunk_start_index = start_info.len.saturating_sub(chunk_start_info.len);
744                    let chunk_end_index =
745                        (chunk.len() as Count).min(end_info.len - chunk_start_info.len);
746
747                    // Return the clipped chunk and index offset.
748                    Ok((
749                        &chunk[chunk_start_index as usize..chunk_end_index as usize],
750                        chunk_start_info.len.saturating_sub(start_info.len) as usize,
751                        fallible_saturating_sub(chunk_start_info.measure, start_info.measure),
752                    ))
753                }
754                RopeSlice(RSEnum::Light { slice, .. }) => Ok((slice, 0, M::Measure::default())),
755            }
756        } else {
757            Err(Error::IndexOutOfBounds(index, self.len()))
758        }
759    }
760
761    /// Non-panicking version of
762    /// [`chunk_at_measure()`][RopeSlice::chunk_at_measure].
763    #[inline]
764    pub fn get_chunk_at_measure(
765        &self,
766        measure: M::Measure,
767        cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering,
768    ) -> Option<(&'a [M], usize, M::Measure)> {
769        // Bounds check
770        if cmp(&measure, &self.measure()).is_lt() {
771            match *self {
772                RopeSlice(RSEnum::Full {
773                    node,
774                    start_info,
775                    end_info,
776                }) => {
777                    let start_measure = measure + start_info.measure;
778                    let (chunk, chunk_start_info) =
779                        node.get_first_chunk_at_measure(start_measure, &cmp);
780
781                    // Calculate clipped start/end indices within the chunk.
782                    let chunk_start_index = start_info.len.saturating_sub(chunk_start_info.len);
783                    let chunk_end_index =
784                        (chunk.len() as Count).min(end_info.len - chunk_start_info.len);
785
786                    // Return the clipped chunk and index offset.
787                    Some((
788                        &chunk[chunk_start_index as usize..chunk_end_index as usize],
789                        chunk_start_info.len.saturating_sub(start_info.len) as usize,
790                        fallible_saturating_sub(chunk_start_info.measure, start_info.measure),
791                    ))
792                }
793                RopeSlice(RSEnum::Light { slice, .. }) => Some((slice, 0, M::Measure::default())),
794            }
795        } else {
796            None
797        }
798    }
799
800    /// Non-panicking version of [`measure_slice()`][RopeSlice::measure_slice].
801    #[inline]
802    pub fn get_measure_slice(
803        &self,
804        range: impl MeasureRange<M>,
805        cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering,
806    ) -> Option<RopeSlice<'a, M>> {
807        let (start, end) = measures_from_range(&range, self.measure()).unwrap();
808
809        if cmp(&start, &M::Measure::default()).is_eq() && cmp(&end, &self.measure()).is_eq() {
810            return Some(self.clone());
811        }
812
813        // Bounds check
814        if cmp(&start, &end).is_le() && cmp(&end, &self.measure()).is_le() {
815            match *self {
816                RopeSlice(RSEnum::Full {
817                    node, start_info, ..
818                }) => Some(RopeSlice::new_with_range(
819                    node,
820                    start_info.measure + start,
821                    start_info.measure + end,
822                    &cmp,
823                )),
824                RopeSlice(RSEnum::Light { slice, .. }) => {
825                    let start_index = start_measure_to_index(slice, start, &cmp);
826                    let end_index = start_measure_to_index(slice, end, cmp);
827                    let new_slice = &slice[start_index..end_index];
828                    Some(RopeSlice(RSEnum::Light { slice: new_slice }))
829                }
830            }
831        } else {
832            None
833        }
834    }
835
836    /// Non-panicking version of [`index_slice()`][RopeSlice::index_slice].
837    #[inline]
838    pub fn get_index_slice<R>(&self, index_range: R) -> Option<RopeSlice<'a, M>>
839    where
840        R: RangeBounds<usize>,
841    {
842        self.get_slice_impl(index_range).ok()
843    }
844
845    pub(crate) fn get_slice_impl<R>(&self, index_range: R) -> Result<RopeSlice<'a, M>, M>
846    where
847        R: RangeBounds<usize>,
848    {
849        let start_range = start_bound_to_num(index_range.start_bound());
850        let end_range = end_bound_to_num(index_range.end_bound());
851
852        // Bounds checks.
853        match (start_range, end_range) {
854            (None, None) => {
855                // Early-out shortcut for taking a slice of the full thing.
856                return Ok(self.clone());
857            }
858            (Some(s), Some(e)) => {
859                if s > e {
860                    return Err(Error::IndexRangeInvalid(s, e));
861                } else if e > self.len() {
862                    return Err(Error::IndexRangeOutOfBounds(
863                        start_range,
864                        end_range,
865                        self.len(),
866                    ));
867                }
868            }
869            (Some(s), None) => {
870                if s > self.len() {
871                    return Err(Error::IndexRangeOutOfBounds(
872                        start_range,
873                        end_range,
874                        self.len(),
875                    ));
876                }
877            }
878            (None, Some(e)) => {
879                if e > self.len() {
880                    return Err(Error::IndexRangeOutOfBounds(
881                        start_range,
882                        end_range,
883                        self.len(),
884                    ));
885                }
886            }
887        }
888
889        let (start, end) = (
890            start_range.unwrap_or(0),
891            end_range.unwrap_or_else(|| self.len()),
892        );
893
894        match *self {
895            RopeSlice(RSEnum::Full {
896                node, start_info, ..
897            }) => RopeSlice::new_with_index_range(
898                node,
899                start_info.len as usize + start,
900                start_info.len as usize + end,
901            ),
902            RopeSlice(RSEnum::Light { slice, .. }) => {
903                let new_slice = &slice[start..end];
904                Ok(RopeSlice(RSEnum::Light { slice: new_slice }))
905            }
906        }
907    }
908
909    /// Non-panicking version of [`iter_at()`][RopeSlice::iter_at].
910    #[inline]
911    pub fn get_iter_at(
912        &self,
913        measure: M::Measure,
914        cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering,
915    ) -> Option<Iter<'a, M>> {
916        // Bounds check
917        if cmp(&measure, &self.measure()).is_le() {
918            match *self {
919                RopeSlice(RSEnum::Full {
920                    node,
921                    start_info,
922                    end_info,
923                }) => Some(Iter::new_with_range_at_measure(
924                    node,
925                    start_info.measure + measure,
926                    (start_info.len as usize, end_info.len as usize),
927                    (start_info.measure, end_info.measure),
928                    cmp,
929                )),
930                RopeSlice(RSEnum::Light { slice, .. }) => {
931                    Some(Iter::from_slice_at(slice, measure, &cmp))
932                }
933            }
934        } else {
935            None
936        }
937    }
938
939    /// Non-panicking version of
940    /// [`chunks_at_index()`][RopeSlice::chunks_at_index].
941    #[inline]
942    pub fn get_chunks_at_index(&self, index: usize) -> Option<(Chunks<'a, M>, usize, M::Measure)> {
943        // Bounds check
944        if index <= self.len() {
945            match *self {
946                RopeSlice(RSEnum::Full {
947                    node,
948                    start_info,
949                    end_info,
950                }) => {
951                    let (chunks, chunk_index, chunk_measure) = Chunks::new_with_range_at_index(
952                        node,
953                        index + start_info.len as usize,
954                        (start_info.len as usize, end_info.len as usize),
955                        (start_info.measure, end_info.measure),
956                    );
957
958                    Some((
959                        chunks,
960                        chunk_index.saturating_sub(start_info.len as usize),
961                        chunk_measure - start_info.measure,
962                    ))
963                }
964                RopeSlice(RSEnum::Light { slice }) => {
965                    let chunks = Chunks::from_slice(slice, index == slice.len());
966
967                    if index == slice.len() {
968                        Some((chunks, slice.len(), measure_of(slice)))
969                    } else {
970                        Some((chunks, 0, M::Measure::default()))
971                    }
972                }
973            }
974        } else {
975            None
976        }
977    }
978
979    /// Non-panicking version of
980    /// [`chunks_at_measure()`][RopeSlice::chunks_at_measure].
981    #[inline]
982    pub fn get_chunks_at_measure(
983        &self,
984        measure: M::Measure,
985        cmp: impl Fn(&M::Measure, &M::Measure) -> Ordering,
986    ) -> Option<(Chunks<'a, M>, usize, M::Measure)> {
987        // Bounds check
988        if cmp(&measure, &self.measure()).is_le() {
989            match *self {
990                RopeSlice(RSEnum::Full {
991                    node,
992                    start_info,
993                    end_info,
994                }) => {
995                    let (chunks, chunk_index, chunk_measure) = Chunks::new_with_range_at_measure(
996                        node,
997                        measure + start_info.measure,
998                        (start_info.len as usize, end_info.len as usize),
999                        (start_info.measure, end_info.measure),
1000                        cmp,
1001                    );
1002
1003                    Some((
1004                        chunks,
1005                        chunk_index.saturating_sub(start_info.len as usize),
1006                        chunk_measure - start_info.measure,
1007                    ))
1008                }
1009                RopeSlice(RSEnum::Light { slice, .. }) => {
1010                    let slice_measure = measure_of(slice);
1011                    let chunks = Chunks::from_slice(slice, cmp(&measure, &slice_measure).is_eq());
1012
1013                    if cmp(&measure, &slice_measure).is_eq() {
1014                        Some((chunks, slice.len(), slice_measure))
1015                    } else {
1016                        Some((chunks, 0, M::Measure::default()))
1017                    }
1018                }
1019            }
1020        } else {
1021            None
1022        }
1023    }
1024}
1025
1026//==============================================================
1027// Conversion impls
1028
1029/// Creates a [`RopeSlice<M>`] directly from a [`&[M]`][Measurable] slice.
1030///
1031/// The useful applications of this are actually somewhat narrow. It is
1032/// intended primarily as an aid when implementing additional functionality
1033/// on top of AnyRope, where you may already have access to a rope chunk and
1034/// want to directly create a [`RopeSlice<M>`] from it, avoiding the overhead of
1035/// going through the slicing APIs.
1036///
1037/// Although it is possible to use this to create [`RopeSlice<M>`]s from
1038/// arbitrary lists, doing so is not especially useful. For example,
1039/// [`Rope<M>`]s and [`RopeSlice<M>`]s can already be directly compared for
1040/// equality with [`Vec<M>`] and [`&[M]`][Measurable] slices.
1041///
1042/// Runs in O(N) time, where N is the length of the slice.
1043impl<'a, M> From<&'a [M]> for RopeSlice<'a, M>
1044where
1045    M: Measurable,
1046    [(); max_len::<M, M::Measure>()]: Sized,
1047    [(); max_children::<M, M::Measure>()]: Sized,
1048{
1049    #[inline]
1050    fn from(slice: &'a [M]) -> Self {
1051        RopeSlice(RSEnum::Light { slice })
1052    }
1053}
1054
1055impl<'a, M> From<RopeSlice<'a, M>> for Vec<M>
1056where
1057    M: Measurable,
1058    [(); max_len::<M, M::Measure>()]: Sized,
1059    [(); max_children::<M, M::Measure>()]: Sized,
1060{
1061    #[inline]
1062    fn from(s: RopeSlice<'a, M>) -> Self {
1063        let mut vec = Vec::with_capacity(s.len());
1064        vec.extend(s.chunks().flat_map(|chunk| chunk.iter()).cloned());
1065        vec
1066    }
1067}
1068
1069/// Attempts to borrow the contents of the slice, but will convert to an
1070/// owned [`Vec<M>`] if the contents is not contiguous in memory.
1071///
1072/// Runs in best case O(1), worst case O(N).
1073impl<'a, M> From<RopeSlice<'a, M>> for std::borrow::Cow<'a, [M]>
1074where
1075    M: Measurable,
1076    [(); max_len::<M, M::Measure>()]: Sized,
1077    [(); max_children::<M, M::Measure>()]: Sized,
1078{
1079    #[inline]
1080    fn from(s: RopeSlice<'a, M>) -> Self {
1081        if let Some(slice) = s.as_slice() {
1082            std::borrow::Cow::Borrowed(slice)
1083        } else {
1084            std::borrow::Cow::Owned(Vec::from(s))
1085        }
1086    }
1087}
1088
1089//==============================================================
1090// Other impls
1091
1092impl<'a, M> std::fmt::Debug for RopeSlice<'a, M>
1093where
1094    M: Measurable + std::fmt::Debug,
1095    [(); max_len::<M, M::Measure>()]: Sized,
1096    [(); max_children::<M, M::Measure>()]: Sized,
1097{
1098    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1099        f.debug_list().entries(self.chunks()).finish()
1100    }
1101}
1102
1103impl<'a, M> std::fmt::Display for RopeSlice<'a, M>
1104where
1105    M: Measurable + std::fmt::Display,
1106    [(); max_len::<M, M::Measure>()]: Sized,
1107    [(); max_children::<M, M::Measure>()]: Sized,
1108{
1109    #[inline]
1110    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1111        f.write_str("[")?;
1112
1113        let mut iter = self.iter();
1114        iter.next()
1115            .map(|(_, measurable)| f.write_fmt(format_args!("{}", measurable)))
1116            .transpose()?;
1117
1118        for (_, measurable) in iter {
1119            f.write_fmt(format_args!(", {}", measurable))?;
1120        }
1121        f.write_str("]")
1122    }
1123}
1124
1125impl<'a, M> std::cmp::Eq for RopeSlice<'a, M>
1126where
1127    M: Measurable + Eq,
1128    [(); max_len::<M, M::Measure>()]: Sized,
1129    [(); max_children::<M, M::Measure>()]: Sized,
1130{
1131}
1132
1133impl<'a, 'b, M> std::cmp::PartialEq<RopeSlice<'b, M>> for RopeSlice<'a, M>
1134where
1135    M: Measurable + PartialEq,
1136    [(); max_len::<M, M::Measure>()]: Sized,
1137    [(); max_children::<M, M::Measure>()]: Sized,
1138{
1139    fn eq(&self, other: &RopeSlice<'b, M>) -> bool {
1140        if self.len() != other.len() {
1141            return false;
1142        }
1143
1144        let mut chunk_itr_1 = self.chunks();
1145        let mut chunk_itr_2 = other.chunks();
1146        let mut chunk1 = chunk_itr_1.next().unwrap_or(&[]);
1147        let mut chunk2 = chunk_itr_2.next().unwrap_or(&[]);
1148
1149        loop {
1150            if chunk1.len() > chunk2.len() {
1151                if &chunk1[..chunk2.len()] != chunk2 {
1152                    return false;
1153                } else {
1154                    chunk1 = &chunk1[chunk2.len()..];
1155                    chunk2 = &[];
1156                }
1157            } else if &chunk2[..chunk1.len()] != chunk1 {
1158                return false;
1159            } else {
1160                chunk2 = &chunk2[chunk1.len()..];
1161                chunk1 = &[];
1162            }
1163
1164            if chunk1.is_empty() {
1165                if let Some(chunk) = chunk_itr_1.next() {
1166                    chunk1 = chunk;
1167                } else {
1168                    break;
1169                }
1170            }
1171
1172            if chunk2.is_empty() {
1173                if let Some(chunk) = chunk_itr_2.next() {
1174                    chunk2 = chunk;
1175                } else {
1176                    break;
1177                }
1178            }
1179        }
1180
1181        return true;
1182    }
1183}
1184
1185impl<'a, 'b, M> std::cmp::PartialEq<&'b [M]> for RopeSlice<'a, M>
1186where
1187    M: Measurable + PartialEq,
1188    [(); max_len::<M, M::Measure>()]: Sized,
1189    [(); max_children::<M, M::Measure>()]: Sized,
1190{
1191    #[inline]
1192    fn eq(&self, other: &&'b [M]) -> bool {
1193        match *self {
1194            RopeSlice(RSEnum::Full { .. }) => {
1195                if self.len() != other.len() {
1196                    return false;
1197                }
1198
1199                let mut index = 0;
1200                for chunk in self.chunks() {
1201                    if chunk != &other[index..(index + chunk.len())] {
1202                        return false;
1203                    }
1204                    index += chunk.len();
1205                }
1206
1207                return true;
1208            }
1209            RopeSlice(RSEnum::Light { slice, .. }) => {
1210                return slice == *other;
1211            }
1212        }
1213    }
1214}
1215
1216impl<'a, 'b, M> std::cmp::PartialEq<RopeSlice<'a, M>> for &'b [M]
1217where
1218    M: Measurable + PartialEq,
1219    [(); max_len::<M, M::Measure>()]: Sized,
1220    [(); max_children::<M, M::Measure>()]: Sized,
1221{
1222    #[inline]
1223    fn eq(&self, other: &RopeSlice<'a, M>) -> bool {
1224        other == self
1225    }
1226}
1227
1228impl<'a, M> std::cmp::PartialEq<[M]> for RopeSlice<'a, M>
1229where
1230    M: Measurable + PartialEq,
1231    [(); max_len::<M, M::Measure>()]: Sized,
1232    [(); max_children::<M, M::Measure>()]: Sized,
1233{
1234    #[inline]
1235    fn eq(&self, other: &[M]) -> bool {
1236        std::cmp::PartialEq::<&[M]>::eq(self, &other)
1237    }
1238}
1239
1240impl<'a, M> std::cmp::PartialEq<RopeSlice<'a, M>> for [M]
1241where
1242    M: Measurable + PartialEq,
1243    [(); max_len::<M, M::Measure>()]: Sized,
1244    [(); max_children::<M, M::Measure>()]: Sized,
1245{
1246    #[inline]
1247    fn eq(&self, other: &RopeSlice<'a, M>) -> bool {
1248        std::cmp::PartialEq::<&[M]>::eq(other, &self)
1249    }
1250}
1251
1252impl<'a, M> std::cmp::PartialEq<Vec<M>> for RopeSlice<'a, M>
1253where
1254    M: Measurable + PartialEq,
1255    [(); max_len::<M, M::Measure>()]: Sized,
1256    [(); max_children::<M, M::Measure>()]: Sized,
1257{
1258    #[inline]
1259    fn eq(&self, other: &Vec<M>) -> bool {
1260        self == other.as_slice()
1261    }
1262}
1263
1264impl<'a, M> std::cmp::PartialEq<RopeSlice<'a, M>> for Vec<M>
1265where
1266    M: Measurable + PartialEq,
1267    [(); max_len::<M, M::Measure>()]: Sized,
1268    [(); max_children::<M, M::Measure>()]: Sized,
1269{
1270    #[inline]
1271    fn eq(&self, other: &RopeSlice<'a, M>) -> bool {
1272        self.as_slice() == other
1273    }
1274}
1275
1276impl<'a, 'b, M> std::cmp::PartialEq<std::borrow::Cow<'b, [M]>> for RopeSlice<'a, M>
1277where
1278    M: Measurable + PartialEq,
1279    [(); max_len::<M, M::Measure>()]: Sized,
1280    [(); max_children::<M, M::Measure>()]: Sized,
1281{
1282    #[inline]
1283    fn eq(&self, other: &std::borrow::Cow<'b, [M]>) -> bool {
1284        *self == **other
1285    }
1286}
1287
1288impl<'a, 'b, M> std::cmp::PartialEq<RopeSlice<'a, M>> for std::borrow::Cow<'b, [M]>
1289where
1290    M: Measurable + PartialEq,
1291    [(); max_len::<M, M::Measure>()]: Sized,
1292    [(); max_children::<M, M::Measure>()]: Sized,
1293{
1294    #[inline]
1295    fn eq(&self, other: &RopeSlice<'a, M>) -> bool {
1296        **self == *other
1297    }
1298}
1299
1300impl<'a, M> std::cmp::PartialEq<Rope<M>> for RopeSlice<'a, M>
1301where
1302    M: Measurable + PartialEq,
1303    [(); max_len::<M, M::Measure>()]: Sized,
1304    [(); max_children::<M, M::Measure>()]: Sized,
1305{
1306    #[inline]
1307    fn eq(&self, other: &Rope<M>) -> bool {
1308        *self == other.measure_slice(.., M::Measure::fallible_cmp)
1309    }
1310}
1311
1312impl<'a, M> std::cmp::PartialEq<RopeSlice<'a, M>> for Rope<M>
1313where
1314    M: Measurable + PartialEq,
1315    [(); max_len::<M, M::Measure>()]: Sized,
1316    [(); max_children::<M, M::Measure>()]: Sized,
1317{
1318    #[inline]
1319    fn eq(&self, other: &RopeSlice<'a, M>) -> bool {
1320        self.measure_slice(.., M::Measure::fallible_cmp) == *other
1321    }
1322}
1323
1324impl<'a, M> std::cmp::Ord for RopeSlice<'a, M>
1325where
1326    M: Measurable + Ord,
1327    [(); max_len::<M, M::Measure>()]: Sized,
1328    [(); max_children::<M, M::Measure>()]: Sized,
1329{
1330    #[allow(clippy::op_ref)] // Erroneously thinks with can directly use a slice.
1331    fn cmp(&self, other: &RopeSlice<'a, M>) -> std::cmp::Ordering {
1332        let mut chunk_itr_1 = self.chunks();
1333        let mut chunk_itr_2 = other.chunks();
1334        let mut chunk1 = chunk_itr_1.next().unwrap_or(&[]);
1335        let mut chunk2 = chunk_itr_2.next().unwrap_or(&[]);
1336
1337        loop {
1338            if chunk1.len() >= chunk2.len() {
1339                let compared = chunk1[..chunk2.len()].cmp(chunk2);
1340                if compared != std::cmp::Ordering::Equal {
1341                    return compared;
1342                }
1343
1344                chunk1 = &chunk1[chunk2.len()..];
1345                chunk2 = &[];
1346            } else {
1347                let compared = chunk1.cmp(&chunk2[..chunk1.len()]);
1348                if compared != std::cmp::Ordering::Equal {
1349                    return compared;
1350                }
1351
1352                chunk1 = &[];
1353                chunk2 = &chunk2[chunk1.len()..];
1354            }
1355
1356            if chunk1.is_empty() {
1357                if let Some(chunk) = chunk_itr_1.next() {
1358                    chunk1 = chunk;
1359                } else {
1360                    break;
1361                }
1362            }
1363
1364            if chunk2.is_empty() {
1365                if let Some(chunk) = chunk_itr_2.next() {
1366                    chunk2 = chunk;
1367                } else {
1368                    break;
1369                }
1370            }
1371        }
1372
1373        self.len().cmp(&other.len())
1374    }
1375}
1376
1377impl<'a, 'b, M> std::cmp::PartialOrd<RopeSlice<'b, M>> for RopeSlice<'a, M>
1378where
1379    M: Measurable + PartialOrd + Ord,
1380    [(); max_len::<M, M::Measure>()]: Sized,
1381    [(); max_children::<M, M::Measure>()]: Sized,
1382{
1383    #[inline]
1384    fn partial_cmp(&self, other: &RopeSlice<'b, M>) -> Option<std::cmp::Ordering> {
1385        Some(self.cmp(other))
1386    }
1387}
1388
1389//===========================================================
1390
1391#[cfg(test)]
1392mod tests {
1393    use crate::{
1394        slice_utils::{index_to_measure, start_measure_to_index},
1395        Rope, Width,
1396    };
1397
1398    /// 70 elements, total measure of 135.
1399    fn pseudo_random() -> Vec<Width> {
1400        (0..70)
1401            .map(|num| match num % 14 {
1402                0 | 7 => Width(1),
1403                1 | 8 => Width(2),
1404                2 => Width(4),
1405                3 | 10 => Width(0),
1406                4 | 11 => Width(0),
1407                5 => Width(5),
1408                6 => Width(1),
1409                9 => Width(8),
1410                12 => Width(3),
1411                13 => Width(0),
1412                _ => unreachable!(),
1413            })
1414            .collect()
1415    }
1416
1417    #[test]
1418    fn len_01() {
1419        let rope = Rope::from_slice(pseudo_random().as_slice());
1420        let slice = rope.measure_slice(7..30, usize::cmp);
1421        assert_eq!(slice.len(), 13);
1422    }
1423
1424    #[test]
1425    fn len_02() {
1426        let rope = Rope::from_slice(pseudo_random().as_slice());
1427        let slice = rope.measure_slice(43..43, usize::cmp);
1428        assert_eq!(slice.len(), 0);
1429    }
1430
1431    #[test]
1432    fn measure_01() {
1433        let rope = Rope::from_slice(pseudo_random().as_slice());
1434        let slice = rope.measure_slice(7..30, usize::cmp);
1435        assert_eq!(slice.measure(), 23);
1436    }
1437
1438    #[test]
1439    fn measure_02() {
1440        let rope = Rope::from_slice(pseudo_random().as_slice());
1441        let slice = rope.measure_slice(43..43, usize::cmp);
1442        assert_eq!(slice.measure(), 0);
1443    }
1444
1445    #[test]
1446    fn measure_03() {
1447        let rope = Rope::from_slice(pseudo_random().as_slice());
1448        let slice = rope.measure_slice(6..30, usize::cmp);
1449        assert_eq!(slice.measure(), 24);
1450    }
1451
1452    #[test]
1453    fn index_to_measure_01() {
1454        let rope = Rope::from_slice(pseudo_random().as_slice());
1455        let slice = rope.measure_slice(88.., usize::cmp);
1456
1457        assert_eq!(slice.index_to_measure(0), 0); // Width(0): 0
1458        assert_eq!(slice.index_to_measure(1), 0); // Width(0): 0
1459        assert_eq!(slice.index_to_measure(2), 0); // Width("hello"): 5
1460        assert_eq!(slice.index_to_measure(3), 5); // Width(true): 1
1461        assert_eq!(slice.index_to_measure(4), 6); // Width(1): 1
1462        assert_eq!(slice.index_to_measure(5), 7); // Width(2): 2
1463        assert_eq!(slice.index_to_measure(6), 9); // Width(8): 8
1464        assert_eq!(slice.index_to_measure(7), 17); // Width(0): 0
1465        assert_eq!(slice.index_to_measure(8), 17); // Width(0): 0
1466        assert_eq!(slice.index_to_measure(9), 17); // Width("bye"): 3
1467        assert_eq!(slice.index_to_measure(10), 20); // Width(false): 0
1468        assert_eq!(slice.index_to_measure(11), 20); // Width(0): 1
1469        assert_eq!(slice.index_to_measure(12), 21); // Width(0): 2
1470        assert_eq!(slice.index_to_measure(13), 23); // Width(4): 4
1471    }
1472
1473    #[test]
1474    fn measure_to_index_01() {
1475        let rope = Rope::from_slice(pseudo_random().as_slice());
1476        let slice = rope.measure_slice(88..135, usize::cmp);
1477
1478        // NOTE: For some elements, it may seem like the amount of "measures"
1479        // that correspond to their index may not match their actual measure.
1480        // For example, `Width("bye")` only lasts for 2 measures, even
1481        // though its measure is 3.
1482        // This is because there are 0 measure elements preceding it, and the
1483        // measure in `measure_to_index()` merely corresponds to the end of an
1484        // element, and has no relation to the referred element's measure.
1485        assert_eq!(slice.start_measure_to_index(0, usize::cmp), 0);
1486        assert_eq!(slice.start_measure_to_index(1, usize::cmp), 2);
1487        assert_eq!(slice.start_measure_to_index(4, usize::cmp), 2);
1488        assert_eq!(slice.start_measure_to_index(5, usize::cmp), 3);
1489        assert_eq!(slice.start_measure_to_index(6, usize::cmp), 4);
1490        assert_eq!(slice.start_measure_to_index(7, usize::cmp), 5);
1491        assert_eq!(slice.start_measure_to_index(8, usize::cmp), 5);
1492        assert_eq!(slice.start_measure_to_index(9, usize::cmp), 6);
1493        assert_eq!(slice.start_measure_to_index(16, usize::cmp), 6);
1494        assert_eq!(slice.start_measure_to_index(17, usize::cmp), 7);
1495        assert_eq!(slice.start_measure_to_index(18, usize::cmp), 9);
1496        assert_eq!(slice.start_measure_to_index(19, usize::cmp), 9);
1497        assert_eq!(slice.start_measure_to_index(20, usize::cmp), 10);
1498        assert_eq!(slice.start_measure_to_index(21, usize::cmp), 12);
1499        assert_eq!(slice.start_measure_to_index(22, usize::cmp), 12);
1500        assert_eq!(slice.start_measure_to_index(23, usize::cmp), 13);
1501        assert_eq!(slice.start_measure_to_index(24, usize::cmp), 13);
1502    }
1503
1504    #[test]
1505    fn from_index_01() {
1506        let rope = Rope::from_slice(pseudo_random().as_slice());
1507        let slice = rope.measure_slice(34..100, usize::cmp);
1508
1509        assert_eq!(slice.from_index(0), (0, Width(0)));
1510        assert_eq!(slice.from_index(10), (20, Width(0)));
1511
1512        assert_eq!(slice.from_index(slice.len() - 3), (60, Width(1)));
1513        assert_eq!(slice.from_index(slice.len() - 2), (61, Width(2)));
1514        assert_eq!(slice.from_index(slice.len() - 1), (63, Width(8)));
1515    }
1516
1517    #[test]
1518    #[should_panic]
1519    fn from_index_02() {
1520        let rope = Rope::from_slice(pseudo_random().as_slice());
1521        let slice = rope.measure_slice(34..100, usize::cmp);
1522        slice.from_index(slice.len());
1523    }
1524
1525    #[test]
1526    #[should_panic]
1527    fn from_index_03() {
1528        let rope = Rope::from_slice(pseudo_random().as_slice());
1529        let slice = rope.measure_slice(42..42, usize::cmp);
1530        slice.from_index(0);
1531    }
1532
1533    #[test]
1534    fn from_measure_01() {
1535        let rope = Rope::from_slice(pseudo_random().as_slice());
1536        let slice = rope.measure_slice(34..100, usize::cmp);
1537
1538        assert_eq!(slice.from_measure(0, usize::cmp), (0, Width(0)));
1539        assert_eq!(slice.from_measure(3, usize::cmp), (0, Width(5)));
1540        assert_eq!(slice.from_measure(5, usize::cmp), (5, Width(1)));
1541        assert_eq!(slice.from_measure(6, usize::cmp), (6, Width(1)));
1542        assert_eq!(slice.from_measure(10, usize::cmp), (9, Width(8)));
1543        assert_eq!(slice.from_measure(65, usize::cmp), (63, Width(8)));
1544    }
1545
1546    #[test]
1547    #[should_panic]
1548    fn from_measure_02() {
1549        let rope = Rope::from_slice(pseudo_random().as_slice());
1550        let slice = rope.measure_slice(34..100, usize::cmp);
1551        slice.from_measure(66, usize::cmp);
1552    }
1553
1554    #[test]
1555    #[should_panic]
1556    fn from_measure_03() {
1557        let rope = Rope::from_slice(pseudo_random().as_slice());
1558        let slice = rope.measure_slice(43..43, usize::cmp);
1559        slice.from_measure(0, usize::cmp);
1560    }
1561
1562    #[test]
1563    fn chunk_at_index_01() {
1564        let rope = Rope::from_slice(pseudo_random().as_slice());
1565        let slice_1 = rope.measure_slice(34..135, usize::cmp);
1566        let slice_2 = &pseudo_random()[17..70];
1567        // "'slice a fine day, isn't it?\nAren't you glad \
1568        //  we're alive?\nこんにちは、みん"
1569
1570        let mut total = slice_2;
1571        let mut prev_chunk = [].as_slice();
1572        for i in 0..slice_1.len() {
1573            let (chunk, index, measure) = slice_1.chunk_at_index(i);
1574            assert_eq!(measure, index_to_measure(slice_2, index));
1575            if chunk != prev_chunk {
1576                assert_eq!(chunk, &total[..chunk.len()]);
1577                total = &total[chunk.len()..];
1578                prev_chunk = chunk;
1579            }
1580
1581            let measure_1 = slice_2.get(i).unwrap();
1582            let measure_2 = {
1583                let i2 = i - index;
1584                chunk.get(i2).unwrap()
1585            };
1586            assert_eq!(measure_1, measure_2);
1587        }
1588
1589        assert_eq!(total.len(), 0);
1590    }
1591
1592    #[test]
1593    fn chunk_at_measure_01() {
1594        let rope = Rope::from_slice(pseudo_random().as_slice());
1595        let slice_1 = rope.measure_slice(34..96, usize::cmp);
1596        let slice_2 = &pseudo_random()[17..51];
1597
1598        let mut remainder = slice_2;
1599        let mut prev_chunk = [].as_slice();
1600
1601        for i in 0..slice_1.measure() {
1602            let (chunk, _, measure) = slice_1.chunk_at_measure(i, usize::cmp);
1603            if chunk != prev_chunk {
1604                assert_eq!(chunk, &remainder[..chunk.len()]);
1605                remainder = &remainder[chunk.len()..];
1606                prev_chunk = chunk;
1607            }
1608
1609            let measure_1 = {
1610                let index_1 = start_measure_to_index(slice_2, i, usize::cmp);
1611                slice_2.get(index_1).unwrap()
1612            };
1613            let measure_2 = {
1614                let index_2 = start_measure_to_index(chunk, i - measure, usize::cmp);
1615                chunk.get(index_2)
1616            };
1617            if let Some(measure_2) = measure_2 {
1618                assert_eq!(measure_1, measure_2);
1619            }
1620        }
1621        assert_eq!(remainder.len(), 0);
1622    }
1623
1624    #[test]
1625    fn slice_01() {
1626        let rope = Rope::from_slice(pseudo_random().as_slice());
1627        let slice_1 = rope.measure_slice(.., usize::cmp);
1628
1629        let slice_2 = slice_1.measure_slice(.., usize::cmp);
1630
1631        assert_eq!(pseudo_random(), slice_2);
1632    }
1633
1634    #[test]
1635    fn slice_02() {
1636        let rope = Rope::from_slice(pseudo_random().as_slice());
1637        let slice_1 = rope.measure_slice(5..43, usize::cmp);
1638
1639        let slice_2 = slice_1.measure_slice(3..25, usize::cmp);
1640
1641        assert_eq!(&pseudo_random()[2..13], slice_2);
1642    }
1643
1644    #[test]
1645    fn slice_03() {
1646        let rope = Rope::from_slice(pseudo_random().as_slice());
1647        let slice_1 = rope.measure_slice(31..97, usize::cmp);
1648
1649        let slice_2 = slice_1.measure_slice(7..64, usize::cmp);
1650
1651        assert_eq!(&pseudo_random()[17..48], slice_2);
1652    }
1653
1654    #[test]
1655    fn slice_04() {
1656        let rope = Rope::from_slice(pseudo_random().as_slice());
1657        let slice_1 = rope.measure_slice(5..43, usize::cmp);
1658
1659        // A range in the middle of a list of 0 elements should capture all of
1660        // them.
1661        let slice_2 = slice_1.measure_slice(24..24, usize::cmp);
1662
1663        assert_eq!(slice_2, [Width(0), Width(0)].as_slice());
1664    }
1665
1666    #[test]
1667    #[should_panic]
1668    fn slice_05() {
1669        let rope = Rope::from_slice(pseudo_random().as_slice());
1670        let slice = rope.measure_slice(5..43, usize::cmp);
1671
1672        #[allow(clippy::reversed_empty_ranges)]
1673        slice.measure_slice(21..20, usize::cmp); // Wrong ordering on purpose.
1674    }
1675
1676    #[test]
1677    #[should_panic]
1678    fn slice_07() {
1679        let rope = Rope::from_slice(pseudo_random().as_slice());
1680        let slice = rope.measure_slice(5..43, usize::cmp);
1681
1682        slice.measure_slice(37..39, usize::cmp);
1683    }
1684
1685    #[test]
1686    fn eq_slice_01() {
1687        let rope = Rope::from_slice(pseudo_random().as_slice());
1688        let slice = rope.measure_slice(.., usize::cmp);
1689
1690        assert_eq!(slice, pseudo_random());
1691        assert_eq!(pseudo_random(), slice);
1692    }
1693
1694    #[test]
1695    fn eq_slice_02() {
1696        let rope = Rope::from_slice(pseudo_random().as_slice());
1697        let slice = rope.measure_slice(0..20, usize::cmp);
1698
1699        assert_ne!(slice, pseudo_random());
1700        assert_ne!(pseudo_random(), slice);
1701    }
1702
1703    #[test]
1704    fn eq_slice_03() {
1705        let mut rope = Rope::from_slice(pseudo_random().as_slice());
1706        rope.remove_inclusive(20..20, usize::cmp);
1707        rope.insert_slice(20, &[Width(5)], usize::cmp);
1708        let slice = rope.measure_slice(.., usize::cmp);
1709
1710        assert_ne!(slice, pseudo_random());
1711        assert_ne!(pseudo_random(), slice);
1712    }
1713
1714    #[test]
1715    fn eq_slice_04() {
1716        let rope = Rope::from_slice(pseudo_random().as_slice());
1717        let slice = rope.measure_slice(.., usize::cmp);
1718        let vec: Vec<Width> = rope.clone().into();
1719
1720        assert_eq!(slice, vec);
1721        assert_eq!(vec, slice);
1722    }
1723
1724    #[test]
1725    fn eq_rope_slice_01() {
1726        let rope = Rope::from_slice(pseudo_random().as_slice());
1727        let slice = rope.measure_slice(43..43, usize::cmp);
1728
1729        assert_eq!(slice, slice);
1730    }
1731
1732    #[test]
1733    fn eq_rope_slice_02() {
1734        let rope = Rope::from_slice(pseudo_random().as_slice());
1735        let slice_1 = rope.measure_slice(43..97, usize::cmp);
1736        let slice_2 = rope.measure_slice(43..97, usize::cmp);
1737
1738        assert_eq!(slice_1, slice_2);
1739    }
1740
1741    #[test]
1742    fn eq_rope_slice_03() {
1743        let rope = Rope::from_slice(pseudo_random().as_slice());
1744        let slice_1 = rope.measure_slice(43..43, usize::cmp);
1745        let slice_2 = rope.measure_slice(43..45, usize::cmp);
1746
1747        assert_ne!(slice_1, slice_2);
1748    }
1749
1750    #[test]
1751    fn eq_rope_slice_04() {
1752        let rope = Rope::from_slice(pseudo_random().as_slice());
1753        let slice_1 = rope.measure_slice(43..45, usize::cmp);
1754        let slice_2 = rope.measure_slice(43..43, usize::cmp);
1755
1756        assert_ne!(slice_1, slice_2);
1757    }
1758
1759    #[test]
1760    fn eq_rope_slice_05() {
1761        let rope: Rope<Width> = Rope::from_slice([].as_slice());
1762        let slice = rope.measure_slice(0..0, usize::cmp);
1763
1764        assert_eq!(slice, slice);
1765    }
1766
1767    #[test]
1768    fn cmp_rope_slice_01() {
1769        let rope_1 = Rope::from_slice(pseudo_random().as_slice());
1770        let rope_2 = Rope::from_slice(pseudo_random().as_slice());
1771        let slice_1 = rope_1.measure_slice(.., usize::cmp);
1772        let slice_2 = rope_2.measure_slice(.., usize::cmp);
1773
1774        assert_eq!(slice_1.cmp(&slice_2), std::cmp::Ordering::Equal);
1775        assert_eq!(
1776            slice_1.measure_slice(..24, usize::cmp).cmp(&slice_2),
1777            std::cmp::Ordering::Less
1778        );
1779        assert_eq!(
1780            slice_1.cmp(&slice_2.measure_slice(..24, usize::cmp)),
1781            std::cmp::Ordering::Greater
1782        );
1783    }
1784
1785    #[test]
1786    fn cmp_rope_slice_02() {
1787        let rope_1 = Rope::from_slice(&[Width(3), Width(1), Width(2), Width(1)]);
1788        let rope_2 = Rope::from_slice(&[Width(3), Width(0), Width(2), Width(1)]);
1789        let slice_1 = rope_1.measure_slice(.., usize::cmp);
1790        let slice_2 = rope_2.measure_slice(.., usize::cmp);
1791
1792        assert_eq!(slice_1.cmp(&slice_2), std::cmp::Ordering::Greater);
1793        assert_eq!(slice_2.cmp(&slice_1), std::cmp::Ordering::Less);
1794    }
1795
1796    #[test]
1797    fn to_vec_01() {
1798        let rope = Rope::from_slice(pseudo_random().as_slice());
1799        let slice = rope.measure_slice(.., usize::cmp);
1800        let vec: Vec<Width> = slice.into();
1801
1802        assert_eq!(rope, vec);
1803        assert_eq!(vec, slice);
1804    }
1805
1806    #[test]
1807    fn to_vec_02() {
1808        let rope = Rope::from_slice(pseudo_random().as_slice());
1809        let slice = rope.measure_slice(0..24, usize::cmp);
1810        let vec: Vec<Width> = slice.into();
1811
1812        assert_eq!(slice, vec);
1813    }
1814
1815    #[test]
1816    fn to_vec_03() {
1817        let rope = Rope::from_slice(pseudo_random().as_slice());
1818        let slice = rope.measure_slice(13..89, usize::cmp);
1819        let vec: Vec<Width> = slice.into();
1820
1821        assert_eq!(slice, vec);
1822    }
1823
1824    #[test]
1825    fn to_vec_04() {
1826        let rope = Rope::from_slice(pseudo_random().as_slice());
1827        let slice = rope.measure_slice(13..41, usize::cmp);
1828        let vec: Vec<Width> = slice.into();
1829
1830        assert_eq!(slice, vec);
1831    }
1832
1833    #[test]
1834    fn to_cow_01() {
1835        use std::borrow::Cow;
1836        let rope = Rope::from_slice(pseudo_random().as_slice());
1837        let slice = rope.measure_slice(13..83, usize::cmp);
1838        let cow: Cow<[Width]> = slice.into();
1839
1840        assert_eq!(slice, cow);
1841    }
1842
1843    #[test]
1844    fn to_cow_02() {
1845        use std::borrow::Cow;
1846        let rope = Rope::from_slice(pseudo_random().as_slice());
1847        let slice = rope.measure_slice(13..14, usize::cmp);
1848        let cow: Cow<[Width]> = rope.measure_slice(13..14, usize::cmp).into();
1849
1850        // Make sure it's borrowed.
1851        if let Cow::Owned(_) = cow {
1852            panic!("Small Cow conversions should result in a borrow.");
1853        }
1854
1855        assert_eq!(slice, cow);
1856    }
1857}