crop/rope/
iterators.rs

1use super::metrics::{ByteMetric, LineMetric, RawLineMetric};
2use super::rope::RopeChunk;
3use super::{Rope, RopeSlice};
4use crate::tree::{Leaves, Units};
5
6/// An iterator over the `&str` chunks of `Rope`s and `RopeSlice`s.
7///
8/// This struct is created by the `chunks` method on [`Rope`](Rope::chunks())
9/// and [`RopeSlice`](RopeSlice::chunks()). See their documentation for more.
10#[derive(Clone)]
11pub struct Chunks<'a> {
12    leaves: Leaves<'a, { Rope::arity() }, RopeChunk>,
13    forward_extra_right: Option<&'a str>,
14    backward_extra_left: Option<&'a str>,
15}
16
17impl<'a> From<&'a Rope> for Chunks<'a> {
18    #[inline]
19    fn from(rope: &'a Rope) -> Self {
20        let mut leaves = rope.tree.leaves();
21        if rope.is_empty() {
22            let _ = leaves.next();
23        }
24        Self { leaves, forward_extra_right: None, backward_extra_left: None }
25    }
26}
27
28impl<'a> From<&RopeSlice<'a>> for Chunks<'a> {
29    #[inline]
30    fn from(slice: &RopeSlice<'a>) -> Self {
31        let mut leaves = slice.tree_slice.leaves();
32        if slice.is_empty() {
33            let _ = leaves.next();
34        }
35        Self { leaves, forward_extra_right: None, backward_extra_left: None }
36    }
37}
38
39impl<'a> Iterator for Chunks<'a> {
40    type Item = &'a str;
41
42    #[inline]
43    fn next(&mut self) -> Option<Self::Item> {
44        if let Some(extra) = self.forward_extra_right.take() {
45            Some(extra)
46        } else {
47            let Some(chunk) = self.leaves.next() else {
48                return self.backward_extra_left.take();
49            };
50
51            if chunk.left_chunk().is_empty() {
52                #[cfg(feature = "small_chunks")]
53                if chunk.right_chunk().is_empty() {
54                    return self.next();
55                }
56
57                debug_assert!(!chunk.right_chunk().is_empty());
58
59                Some(chunk.right_chunk())
60            } else {
61                if !chunk.right_chunk().is_empty() {
62                    self.forward_extra_right = Some(chunk.right_chunk());
63                }
64                Some(chunk.left_chunk())
65            }
66        }
67    }
68
69    #[inline]
70    fn size_hint(&self) -> (usize, Option<usize>) {
71        let exact = self.leaves.len();
72        (exact, Some(exact * 2))
73    }
74}
75
76impl DoubleEndedIterator for Chunks<'_> {
77    #[inline]
78    fn next_back(&mut self) -> Option<Self::Item> {
79        if let Some(extra) = self.backward_extra_left.take() {
80            Some(extra)
81        } else {
82            let Some(chunk) = self.leaves.next_back() else {
83                return self.forward_extra_right.take();
84            };
85
86            if chunk.right_chunk().is_empty() {
87                #[cfg(feature = "small_chunks")]
88                if chunk.left_chunk().is_empty() {
89                    return self.next_back();
90                }
91
92                debug_assert!(!chunk.left_chunk().is_empty());
93
94                Some(chunk.left_chunk())
95            } else {
96                if !chunk.left_chunk().is_empty() {
97                    self.backward_extra_left = Some(chunk.left_chunk());
98                }
99                Some(chunk.right_chunk())
100            }
101        }
102    }
103}
104
105impl core::iter::FusedIterator for Chunks<'_> {}
106
107/// An iterator over the bytes of `Rope`s and `RopeSlice`s.
108///
109/// This struct is created by the `bytes` method on [`Rope`](Rope::bytes())
110/// and [`RopeSlice`](RopeSlice::bytes()). See their documentation for more.
111#[derive(Clone)]
112pub struct Bytes<'a> {
113    chunks: Chunks<'a>,
114
115    /// The chunk used when calling [`Bytes::next()`].
116    forward_chunk: &'a [u8],
117
118    /// The number of bytes of `forward_chunk` that have already been yielded.
119    forward_byte_idx: usize,
120
121    /// The chunk used when calling [`Bytes::next_back()`].
122    backward_chunk: &'a [u8],
123
124    /// The number of bytes of `backward_chunk` which are yet to be yielded.
125    backward_byte_idx: usize,
126
127    /// The number of bytes that have been yielded so far.
128    bytes_yielded: usize,
129
130    /// The total number of bytes this iterator will yield.
131    bytes_total: usize,
132}
133
134impl<'a> From<&'a Rope> for Bytes<'a> {
135    #[inline]
136    fn from(rope: &'a Rope) -> Self {
137        Self {
138            chunks: rope.chunks(),
139            forward_chunk: &[],
140            forward_byte_idx: 0,
141            backward_chunk: &[],
142            backward_byte_idx: 0,
143            bytes_yielded: 0,
144            bytes_total: rope.byte_len(),
145        }
146    }
147}
148
149impl<'a> From<&RopeSlice<'a>> for Bytes<'a> {
150    #[inline]
151    fn from(slice: &RopeSlice<'a>) -> Self {
152        Self {
153            chunks: slice.chunks(),
154            forward_chunk: &[],
155            forward_byte_idx: 0,
156            backward_chunk: &[],
157            backward_byte_idx: 0,
158            bytes_yielded: 0,
159            bytes_total: slice.byte_len(),
160        }
161    }
162}
163
164impl Iterator for Bytes<'_> {
165    type Item = u8;
166
167    #[inline]
168    fn next(&mut self) -> Option<Self::Item> {
169        if self.forward_byte_idx == self.forward_chunk.len() {
170            if let Some(chunk) = self.chunks.next() {
171                self.forward_chunk = chunk.as_bytes();
172                self.forward_byte_idx = 0;
173            } else if self.backward_byte_idx == 0 {
174                return None;
175            } else {
176                let byte = self.backward_chunk[0];
177                self.backward_chunk = &self.backward_chunk[1..];
178                self.backward_byte_idx -= 1;
179                self.bytes_yielded += 1;
180                return Some(byte);
181            }
182        }
183
184        let byte = self.forward_chunk[self.forward_byte_idx];
185        self.forward_byte_idx += 1;
186        self.bytes_yielded += 1;
187        Some(byte)
188    }
189
190    #[inline]
191    fn size_hint(&self) -> (usize, Option<usize>) {
192        let exact = self.len();
193        (exact, Some(exact))
194    }
195}
196
197impl DoubleEndedIterator for Bytes<'_> {
198    #[inline]
199    fn next_back(&mut self) -> Option<Self::Item> {
200        if self.backward_byte_idx == 0 {
201            if let Some(chunk) = self.chunks.next_back() {
202                self.backward_chunk = chunk.as_bytes();
203                self.backward_byte_idx = chunk.len();
204            } else if self.forward_byte_idx == self.forward_chunk.len() {
205                return None;
206            } else {
207                let byte_idx = self.forward_chunk.len() - 1;
208                let byte = self.forward_chunk[byte_idx];
209                self.forward_chunk = &self.forward_chunk[..byte_idx];
210                self.bytes_yielded += 1;
211                return Some(byte);
212            }
213        }
214
215        self.backward_byte_idx -= 1;
216        let byte = self.backward_chunk[self.backward_byte_idx];
217        self.bytes_yielded += 1;
218        Some(byte)
219    }
220}
221
222impl ExactSizeIterator for Bytes<'_> {
223    #[inline]
224    fn len(&self) -> usize {
225        self.bytes_total - self.bytes_yielded
226    }
227}
228
229impl core::iter::FusedIterator for Bytes<'_> {}
230
231/// An iterator over the code points (i.e. [`char`]s) of `Rope`s and
232/// `RopeSlice`s.
233///
234/// This struct is created by the `chars` method on [`Rope`](Rope::chars())
235/// and [`RopeSlice`](RopeSlice::chars()). See their documentation for more.
236#[derive(Clone)]
237pub struct Chars<'a> {
238    chunks: Chunks<'a>,
239
240    /// The chunk used when calling [`Chars::next()`].
241    forward_chunk: &'a str,
242
243    /// The number of bytes of `forward_chunk` that have already been
244    /// yielded.
245    forward_byte_idx: usize,
246
247    /// The chunk used when calling [`Chars::next_back()`].
248    backward_chunk: &'a str,
249
250    /// The number of bytes of `backward_chunk` which are yet to be yielded.
251    backward_byte_idx: usize,
252}
253
254impl<'a> From<&'a Rope> for Chars<'a> {
255    #[inline]
256    fn from(rope: &'a Rope) -> Self {
257        Self {
258            chunks: rope.chunks(),
259            forward_chunk: "",
260            forward_byte_idx: 0,
261            backward_chunk: "",
262            backward_byte_idx: 0,
263        }
264    }
265}
266
267impl<'a> From<&RopeSlice<'a>> for Chars<'a> {
268    #[inline]
269    fn from(slice: &RopeSlice<'a>) -> Self {
270        Self {
271            chunks: slice.chunks(),
272            forward_chunk: "",
273            forward_byte_idx: 0,
274            backward_chunk: "",
275            backward_byte_idx: 0,
276        }
277    }
278}
279
280impl Iterator for Chars<'_> {
281    type Item = char;
282
283    #[inline]
284    fn next(&mut self) -> Option<Self::Item> {
285        if self.forward_byte_idx == self.forward_chunk.len() {
286            if let Some(chunk) = self.chunks.next() {
287                self.forward_chunk = chunk;
288                self.forward_byte_idx = 0;
289            } else if self.backward_byte_idx == 0 {
290                return None;
291            } else {
292                let ch = unsafe {
293                    self.backward_chunk
294                        .chars()
295                        .next()
296                        // SAFETY: `backward_byte_idx` is greater than zero so
297                        // there are still chars to yield in that chunk.
298                        .unwrap_unchecked()
299                };
300
301                let len = ch.len_utf8();
302                self.backward_chunk = &self.backward_chunk[len..];
303                self.backward_byte_idx -= len;
304                return Some(ch);
305            }
306        }
307
308        let ch = unsafe {
309            self.forward_chunk[self.forward_byte_idx..]
310                .chars()
311                .next()
312                // SAFETY: `forward_byte_idx` is less than the byte length of
313                // `chunk_front`, so there are still chars to yield in this
314                // chunk.
315                .unwrap_unchecked()
316        };
317
318        self.forward_byte_idx += ch.len_utf8();
319
320        Some(ch)
321    }
322}
323
324impl DoubleEndedIterator for Chars<'_> {
325    #[inline]
326    fn next_back(&mut self) -> Option<Self::Item> {
327        if self.backward_byte_idx == 0 {
328            if let Some(chunk) = self.chunks.next_back() {
329                self.backward_chunk = chunk;
330                self.backward_byte_idx = self.backward_chunk.len();
331            } else if self.forward_byte_idx == self.forward_chunk.len() {
332                return None;
333            } else {
334                let ch = unsafe {
335                    self.forward_chunk
336                        .chars()
337                        .next_back()
338                        // SAFETY: `forward_byte_idx` is less than the byte
339                        // length of `chunk_front`, so there are still chars to
340                        // yield in that chunk.
341                        .unwrap_unchecked()
342                };
343
344                self.forward_chunk = &self.forward_chunk
345                    [..self.forward_chunk.len() - ch.len_utf8()];
346
347                return Some(ch);
348            }
349        }
350
351        let ch = unsafe {
352            self.backward_chunk[..self.backward_byte_idx]
353                .chars()
354                .next_back()
355                // SAFETY: `backward_byte_idx` is greater than zero so there
356                // are still chars to yield in this chunk.
357                .unwrap_unchecked()
358        };
359
360        self.backward_byte_idx -= ch.len_utf8();
361
362        Some(ch)
363    }
364}
365
366impl core::iter::FusedIterator for Chars<'_> {}
367
368/// An iterator over the lines of `Rope`s and `RopeSlice`s, including the line
369/// terminators (`\n` or `\r\n`).
370///
371/// This struct is created by the `raw_lines` method on
372/// [`Rope`](Rope::raw_lines()) and [`RopeSlice`](RopeSlice::raw_lines()). See
373/// their documentation for more.
374#[derive(Clone)]
375pub struct RawLines<'a> {
376    units: Units<'a, { Rope::arity() }, RopeChunk, RawLineMetric>,
377
378    /// The number of lines that have been yielded so far.
379    lines_yielded: usize,
380
381    /// The total number of bytes this iterator will yield.
382    lines_total: usize,
383}
384
385impl<'a> From<&'a Rope> for RawLines<'a> {
386    #[inline]
387    fn from(rope: &'a Rope) -> Self {
388        Self {
389            units: rope.tree.units::<RawLineMetric>(),
390            lines_yielded: 0,
391            lines_total: rope.line_len(),
392        }
393    }
394}
395
396impl<'a> From<&RopeSlice<'a>> for RawLines<'a> {
397    #[inline]
398    fn from(slice: &RopeSlice<'a>) -> Self {
399        Self {
400            units: slice.tree_slice.units::<RawLineMetric>(),
401            lines_yielded: 0,
402            lines_total: slice.line_len(),
403        }
404    }
405}
406
407impl<'a> Iterator for RawLines<'a> {
408    type Item = RopeSlice<'a>;
409
410    #[inline]
411    fn next(&mut self) -> Option<Self::Item> {
412        let (tree_slice, _) = self.units.next()?;
413        self.lines_yielded += 1;
414        Some(RopeSlice::from(tree_slice))
415    }
416
417    #[inline]
418    fn size_hint(&self) -> (usize, Option<usize>) {
419        let exact = self.len();
420        (exact, Some(exact))
421    }
422}
423
424impl DoubleEndedIterator for RawLines<'_> {
425    #[inline]
426    fn next_back(&mut self) -> Option<Self::Item> {
427        let (tree_slice, _) = self.units.next_back()?;
428        self.lines_yielded += 1;
429        Some(RopeSlice::from(tree_slice))
430    }
431}
432
433impl ExactSizeIterator for RawLines<'_> {
434    #[inline]
435    fn len(&self) -> usize {
436        self.lines_total - self.lines_yielded
437    }
438}
439
440impl core::iter::FusedIterator for RawLines<'_> {}
441
442/// An iterator over the lines of `Rope`s and `RopeSlice`s, not including the
443/// line terminators (`\n` or `\r\n`).
444///
445/// This struct is created by the `lines` method on [`Rope`](Rope::lines()) and
446/// [`RopeSlice`](RopeSlice::lines()). See their documentation for more.
447#[derive(Clone)]
448pub struct Lines<'a> {
449    units: Units<'a, { Rope::arity() }, RopeChunk, LineMetric>,
450
451    /// The number of lines that have been yielded so far.
452    lines_yielded: usize,
453
454    /// The total number of bytes this iterator will yield.
455    lines_total: usize,
456}
457
458impl<'a> From<&'a Rope> for Lines<'a> {
459    #[inline]
460    fn from(rope: &'a Rope) -> Self {
461        Self {
462            units: rope.tree.units::<LineMetric>(),
463            lines_yielded: 0,
464            lines_total: rope.line_len(),
465        }
466    }
467}
468
469impl<'a> From<&RopeSlice<'a>> for Lines<'a> {
470    #[inline]
471    fn from(slice: &RopeSlice<'a>) -> Self {
472        Self {
473            units: slice.tree_slice.units::<LineMetric>(),
474            lines_yielded: 0,
475            lines_total: slice.line_len(),
476        }
477    }
478}
479
480impl<'a> Iterator for Lines<'a> {
481    type Item = RopeSlice<'a>;
482
483    #[inline]
484    fn next(&mut self) -> Option<Self::Item> {
485        let (tree_slice, ByteMetric(advance)) = self.units.next()?;
486        self.lines_yielded += 1;
487
488        let mut slice = RopeSlice { tree_slice, has_trailing_newline: false };
489
490        // This handles CRLF pairs that have been split across chunks. For
491        // example, if we have "aaa\r" and "\nbbb" we should yield "aaa", but
492        // the tree slice currently contains "aaa\r", so we need to remove
493        // the trailing "\r".
494        if slice.tree_slice.end_slice().last_chunk().ends_with('\r')
495            && advance - slice.byte_len() == 1
496        {
497            slice.truncate_last_char();
498        }
499
500        Some(slice)
501    }
502
503    #[inline]
504    fn size_hint(&self) -> (usize, Option<usize>) {
505        let exact = self.len();
506        (exact, Some(exact))
507    }
508}
509
510impl DoubleEndedIterator for Lines<'_> {
511    #[inline]
512    fn next_back(&mut self) -> Option<Self::Item> {
513        let (tree_slice, ByteMetric(advance)) = self.units.next_back()?;
514        self.lines_yielded += 1;
515
516        let mut slice = RopeSlice { tree_slice, has_trailing_newline: false };
517
518        // Same as above.
519        if slice.tree_slice.end_slice().last_chunk().ends_with('\r')
520            && advance - slice.byte_len() == 1
521        {
522            slice.truncate_last_char();
523        }
524
525        Some(slice)
526    }
527}
528
529impl ExactSizeIterator for Lines<'_> {
530    #[inline]
531    fn len(&self) -> usize {
532        self.lines_total - self.lines_yielded
533    }
534}
535
536impl core::iter::FusedIterator for Lines<'_> {}
537
538#[cfg_attr(docsrs, doc(cfg(feature = "graphemes")))]
539#[cfg(feature = "graphemes")]
540pub use graphemes::Graphemes;
541
542#[cfg(feature = "graphemes")]
543mod graphemes {
544    use alloc::borrow::Cow;
545
546    use unicode_segmentation::{GraphemeCursor, GraphemeIncomplete};
547
548    use super::*;
549
550    /// An iterator over the extended grapheme clusters of `Rope`s and
551    /// `RopeSlice`s.
552    ///
553    /// This struct is created by the `graphemes` method on
554    /// [`Rope`](Rope::graphemes()) and [`RopeSlice`](RopeSlice::graphemes()).
555    /// See their documentation for more.
556    #[derive(Clone)]
557    pub struct Graphemes<'a> {
558        chunks: Chunks<'a>,
559
560        /// The slice we're iterating over, used to provide precontext to the
561        /// `GraphemeCursor`s.
562        slice: RopeSlice<'a>,
563
564        /// The cursor used when calling [`Graphemes::next()`].
565        forward_cursor: GraphemeCursor,
566
567        /// The chunk used when calling [`Graphemes::next()`].
568        forward_chunk: &'a str,
569
570        /// The byte offset of the start of
571        /// [`forward_chunk`](Self::forward_chunk) from the beginning of the
572        /// iterating range, which is also the sum of the bytes of all the
573        /// graphemes that have been yielded by [`Self::next()`].
574        forward_offset: usize,
575
576        /// The cursor used when calling [`Graphemes::next_back()`].
577        backward_cursor: GraphemeCursor,
578
579        /// The chunk used when calling [`Graphemes::next_back()`].
580        backward_chunk: &'a str,
581
582        /// The byte offset of the end of
583        /// [`backward_chunk`](Self::backward_chunk) from the end of the
584        /// iterating range, which is also the sum of the bytes of all the
585        /// graphemes that have been yielded by [`Self::next_back()`].
586        backward_offset: usize,
587    }
588
589    impl<'a> From<&'a Rope> for Graphemes<'a> {
590        #[inline]
591        fn from(rope: &'a Rope) -> Self {
592            let len = rope.byte_len();
593
594            Self {
595                chunks: rope.chunks(),
596                slice: rope.byte_slice(..),
597                forward_cursor: GraphemeCursor::new(0, len, true),
598                forward_offset: 0,
599                forward_chunk: "",
600                backward_cursor: GraphemeCursor::new(len, len, true),
601                backward_chunk: "",
602                backward_offset: len,
603            }
604        }
605    }
606
607    impl<'a> From<&RopeSlice<'a>> for Graphemes<'a> {
608        #[inline]
609        fn from(slice: &RopeSlice<'a>) -> Self {
610            let len = slice.byte_len();
611
612            Self {
613                chunks: slice.chunks(),
614                slice: *slice,
615                forward_cursor: GraphemeCursor::new(0, len, true),
616                forward_offset: 0,
617                forward_chunk: "",
618                backward_cursor: GraphemeCursor::new(len, len, true),
619                backward_chunk: "",
620                backward_offset: len,
621            }
622        }
623    }
624
625    impl<'a> Iterator for Graphemes<'a> {
626        type Item = Cow<'a, str>;
627
628        #[inline]
629        fn next(&mut self) -> Option<Self::Item> {
630            debug_assert_eq!(
631                self.forward_offset,
632                self.forward_cursor.cur_cursor()
633            );
634
635            let mut using_backward_chunk = false;
636
637            if self.forward_chunk.is_empty() {
638                self.forward_chunk = if let Some(next) = self.chunks.next() {
639                    next
640                } else if !self.backward_chunk.is_empty() {
641                    debug_assert!(
642                        self.backward_cursor.cur_cursor()
643                            > self.forward_cursor.cur_cursor()
644                    );
645                    using_backward_chunk = true;
646                    self.backward_chunk
647                } else {
648                    return None;
649                }
650            }
651
652            let mut grapheme = Cow::Borrowed("");
653
654            loop {
655                match self
656                    .forward_cursor
657                    // The chunk passed to `next_boundary` can't be empty or
658                    // it'll panic.
659                    .next_boundary(self.forward_chunk, self.forward_offset)
660                {
661                    Ok(Some(byte_end)) => {
662                        if byte_end == self.forward_offset {
663                            debug_assert!(!grapheme.is_empty());
664                            return Some(grapheme);
665                        }
666
667                        debug_assert!(byte_end > self.forward_offset);
668
669                        let grapheme_end = &self.forward_chunk
670                            [..byte_end - self.forward_offset];
671
672                        match &mut grapheme {
673                            Cow::Borrowed(gr) if gr.is_empty() => {
674                                *gr = grapheme_end;
675                            },
676
677                            Cow::Borrowed(gr) => {
678                                let mut gr = gr.to_owned();
679                                gr.push_str(grapheme_end);
680                                grapheme = Cow::Owned(gr);
681                            },
682
683                            Cow::Owned(gr) => {
684                                gr.push_str(grapheme_end);
685                            },
686                        }
687
688                        self.forward_offset += grapheme_end.len();
689
690                        self.forward_chunk =
691                            &self.forward_chunk[grapheme_end.len()..];
692
693                        if using_backward_chunk {
694                            self.backward_chunk = self.forward_chunk;
695                        }
696
697                        return Some(grapheme);
698                    },
699
700                    Ok(None) => return None,
701
702                    Err(GraphemeIncomplete::NextChunk) => {
703                        match &mut grapheme {
704                            Cow::Borrowed(gr) if gr.is_empty() => {
705                                *gr = self.forward_chunk;
706                            },
707
708                            Cow::Borrowed(gr) => {
709                                let mut gr = gr.to_owned();
710                                gr.push_str(self.forward_chunk);
711                                grapheme = Cow::Owned(gr);
712                            },
713
714                            Cow::Owned(gr) => gr.push_str(self.forward_chunk),
715                        }
716
717                        self.forward_offset += self.forward_chunk.len();
718
719                        self.forward_chunk =
720                            if let Some(next) = self.chunks.next() {
721                                next
722                            } else if !self.backward_chunk.is_empty() {
723                                debug_assert!(
724                                    self.backward_cursor.cur_cursor()
725                                        > self.forward_cursor.cur_cursor()
726                                );
727                                using_backward_chunk = true;
728                                self.backward_chunk
729                            } else {
730                                return None;
731                            }
732                    },
733
734                    // Why does it ask for precontext if we've been feeding it
735                    // stuff from the beginning of the range?
736                    Err(GraphemeIncomplete::PreContext(byte_idx)) => {
737                        let slice = self.slice.byte_slice(..byte_idx);
738                        let chunk = slice.chunks().next_back().unwrap();
739                        self.forward_cursor
740                            .provide_context(chunk, byte_idx - chunk.len());
741                    },
742
743                    Err(_) => {
744                        unreachable!();
745                    },
746                }
747            }
748        }
749
750        #[inline]
751        fn size_hint(&self) -> (usize, Option<usize>) {
752            let hi = self.backward_offset - self.forward_offset;
753            let lo = (hi != 0) as usize;
754            (lo, Some(hi))
755        }
756    }
757
758    impl DoubleEndedIterator for Graphemes<'_> {
759        #[inline]
760        fn next_back(&mut self) -> Option<Self::Item> {
761            debug_assert_eq!(
762                self.backward_offset,
763                self.backward_cursor.cur_cursor()
764            );
765
766            let mut using_forward_chunk = false;
767
768            if self.backward_chunk.is_empty() {
769                self.backward_chunk =
770                    if let Some(prev) = self.chunks.next_back() {
771                        prev
772                    } else if !self.forward_chunk.is_empty() {
773                        debug_assert!(
774                            self.backward_cursor.cur_cursor()
775                                > self.forward_cursor.cur_cursor()
776                        );
777                        using_forward_chunk = true;
778                        self.forward_chunk
779                    } else {
780                        return None;
781                    }
782            }
783
784            let mut grapheme = Cow::Borrowed("");
785
786            loop {
787                match self
788                    .backward_cursor
789                    // The chunk passed to `prev_boundary` can't be empty or
790                    // it'll panic.
791                    .prev_boundary(
792                        self.backward_chunk,
793                        self.backward_cursor.cur_cursor()
794                            - self.backward_chunk.len(),
795                    ) {
796                    Ok(Some(byte_start)) => {
797                        if byte_start == self.backward_offset {
798                            debug_assert!(!grapheme.is_empty());
799                            return Some(grapheme);
800                        }
801
802                        debug_assert!(byte_start < self.backward_offset);
803
804                        let grapheme_start = {
805                            let start_len = self.backward_offset - byte_start;
806                            let chunk_len = self.backward_chunk.len();
807                            &self.backward_chunk[(chunk_len - start_len)..]
808                        };
809
810                        match &mut grapheme {
811                            Cow::Borrowed(gr) if gr.is_empty() => {
812                                *gr = grapheme_start;
813                            },
814
815                            Cow::Borrowed(gr) => {
816                                let mut new = String::with_capacity(
817                                    grapheme_start.len() + gr.len(),
818                                );
819                                new.push_str(grapheme_start);
820                                new.push_str(gr);
821                                grapheme = Cow::Owned(new);
822                            },
823
824                            Cow::Owned(gr) => {
825                                let mut new = String::with_capacity(
826                                    grapheme_start.len() + gr.len(),
827                                );
828                                new.push_str(grapheme_start);
829                                new.push_str(&*gr);
830                                *gr = new;
831                            },
832                        }
833
834                        self.backward_offset -= grapheme_start.len();
835
836                        self.backward_chunk =
837                            &self.backward_chunk[..self.backward_chunk.len()
838                                - grapheme_start.len()];
839
840                        if using_forward_chunk {
841                            self.forward_chunk = self.backward_chunk;
842                        }
843
844                        return Some(grapheme);
845                    },
846
847                    Ok(None) => return None,
848
849                    Err(GraphemeIncomplete::PrevChunk) => {
850                        match &mut grapheme {
851                            Cow::Borrowed(gr) if gr.is_empty() => {
852                                *gr = self.backward_chunk;
853                            },
854
855                            Cow::Borrowed(gr) => {
856                                let mut new = String::with_capacity(
857                                    self.backward_chunk.len() + gr.len(),
858                                );
859                                new.push_str(self.backward_chunk);
860                                new.push_str(gr);
861                                grapheme = Cow::Owned(new);
862                            },
863
864                            Cow::Owned(gr) => {
865                                let mut new = String::with_capacity(
866                                    self.backward_chunk.len() + gr.len(),
867                                );
868                                new.push_str(self.backward_chunk);
869                                new.push_str(gr);
870                                *gr = new;
871                            },
872                        }
873
874                        self.backward_offset -= self.backward_chunk.len();
875
876                        self.backward_chunk =
877                            if let Some(prev) = self.chunks.next_back() {
878                                prev
879                            } else if !self.forward_chunk.is_empty() {
880                                debug_assert!(
881                                    self.backward_cursor.cur_cursor()
882                                        > self.forward_cursor.cur_cursor()
883                                );
884                                using_forward_chunk = true;
885                                self.forward_chunk
886                            } else {
887                                return None;
888                            }
889                    },
890
891                    // Why does it ask for precontext if we're iterating
892                    // backward? Shouldn't it always just ask for the previous
893                    // chunk?
894                    Err(GraphemeIncomplete::PreContext(byte_idx)) => {
895                        let slice = self.slice.byte_slice(..byte_idx);
896                        let chunk = slice.chunks().next_back().unwrap();
897                        self.backward_cursor
898                            .provide_context(chunk, byte_idx - chunk.len());
899                    },
900
901                    Err(_) => {
902                        unreachable!();
903                    },
904                }
905            }
906        }
907    }
908
909    impl core::iter::FusedIterator for Graphemes<'_> {}
910}