Coverage Report

Created: 2026-10-28 07:08

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/ropey-1.6.1/src/iter.rs
Line
Count
Source
1
//! Iterators over a `Rope`'s data.
2
//!
3
//! The iterators in Ropey can be created from both `Rope`s and `RopeSlice`s.
4
//! When created from a `RopeSlice`, they iterate over only the data that the
5
//! `RopeSlice` refers to.  For the `Lines` and `Chunks` iterators, the data
6
//! of the first and last yielded item will be correctly truncated to match
7
//! the bounds of the `RopeSlice`.
8
//!
9
//! # Reverse iteration
10
//!
11
//! All iterators in Ropey operate as a cursor that can move both forwards
12
//! and backwards over its contents.  This can be accomplished via the
13
//! `next()` and `prev()` methods on each iterator, or by using the `reverse()`
14
//! or `reversed()` methods to change the iterator's direction.
15
//!
16
//! Conceptually, an iterator in Ropey is always positioned *between* the
17
//! elements it iterates over, and returns an element when it jumps over it
18
//! via the `next()` or `prev()` methods.
19
//!
20
//! For example, given the text `"abc"` and a `Chars` iterator starting at the
21
//! beginning of the text, you would get the following sequence of states and
22
//! return values by repeatedly calling `next()` (the vertical bar represents
23
//! the position of the iterator):
24
//!
25
//! 0. `|abc`
26
//! 1. `a|bc` -> `Some('a')`
27
//! 2. `ab|c` -> `Some('b')`
28
//! 3. `abc|` -> `Some('c')`
29
//! 4. `abc|` -> `None`
30
//!
31
//! The `prev()` method operates identically, except moving in the opposite
32
//! direction.  And `reverse()` simply swaps the behavior of `prev()` and
33
//! `next()`.
34
//!
35
//! # Creating iterators at any position
36
//!
37
//! Iterators in Ropey can be created starting at any position in the text.
38
//! This is accomplished with the various `bytes_at()`, `chars_at()`, etc.
39
//! methods of `Rope` and `RopeSlice`.
40
//!
41
//! When an iterator is created this way, it is positioned such that a call to
42
//! `next()` will return the specified element, and a call to `prev()` will
43
//! return the element just before the specified one.
44
//!
45
//! Importantly, iterators created this way still have access to the entire
46
//! contents of the `Rope`/`RopeSlice` they were created from—the
47
//! contents before the specified position is not truncated.  For example, you
48
//! can create a `Chars` iterator starting at the end of a `Rope`, and then
49
//! use the `prev()` method to iterate backwards over all of that `Rope`'s
50
//! chars.
51
//!
52
//! # A possible point of confusion
53
//!
54
//! The Rust standard library has an iterator trait `DoubleEndedIterator` with
55
//! a method `rev()`.  While this method's name is very similar to Ropey's
56
//! `reverse()` method, its behavior is very different.
57
//!
58
//! `DoubleEndedIterator` actually provides two iterators: one starting at each
59
//! end of the collection, moving in opposite directions towards each other.
60
//! Calling `rev()` switches between those two iterators, changing not only the
61
//! direction of iteration but also its current position in the collection.
62
//!
63
//! The `reverse()` method on Ropey's iterators, on the other hand, reverses
64
//! the direction of the iterator in-place, without changing its position in
65
//! the text.
66
67
use std::str;
68
use std::sync::Arc;
69
70
use crate::slice::{RSEnum, RopeSlice};
71
use crate::str_utils::{
72
    byte_to_line_idx, char_to_byte_idx, count_chars, count_utf16_surrogates, ends_with_line_break,
73
    last_line_start_byte_idx, line_to_byte_idx, trim_line_break,
74
};
75
use crate::tree::{Count, Node, TextInfo};
76
77
//==========================================================
78
79
/// An iterator over a `Rope`'s bytes.
80
#[derive(Debug, Clone)]
81
pub struct Bytes<'a> {
82
    chunk_iter: Chunks<'a>,
83
    cur_chunk: &'a [u8],
84
    byte_idx: usize,
85
    last_call_was_prev_impl: bool,
86
    bytes_total: usize,
87
    bytes_remaining: usize,
88
    is_reversed: bool,
89
}
90
91
impl<'a> Bytes<'a> {
92
0
    pub(crate) fn new(node: &Arc<Node>) -> Bytes {
93
0
        let mut chunk_iter = Chunks::new(node);
94
0
        let cur_chunk = if let Some(chunk) = chunk_iter.next() {
95
0
            chunk
96
        } else {
97
0
            ""
98
        };
99
0
        Bytes {
100
0
            chunk_iter: chunk_iter,
101
0
            cur_chunk: cur_chunk.as_bytes(),
102
0
            byte_idx: 0,
103
0
            last_call_was_prev_impl: false,
104
0
            bytes_total: node.text_info().bytes as usize,
105
0
            bytes_remaining: node.text_info().bytes as usize,
106
0
            is_reversed: false,
107
0
        }
108
0
    }
109
110
    #[inline(always)]
111
0
    pub(crate) fn new_with_range(
112
0
        node: &Arc<Node>,
113
0
        byte_idx_range: (usize, usize),
114
0
        char_idx_range: (usize, usize),
115
0
        line_break_idx_range: (usize, usize),
116
0
    ) -> Bytes {
117
0
        Bytes::new_with_range_at(
118
0
            node,
119
0
            byte_idx_range.0,
120
0
            byte_idx_range,
121
0
            char_idx_range,
122
0
            line_break_idx_range,
123
        )
124
0
    }
125
126
0
    pub(crate) fn new_with_range_at(
127
0
        node: &Arc<Node>,
128
0
        at_byte: usize,
129
0
        byte_idx_range: (usize, usize),
130
0
        char_idx_range: (usize, usize),
131
0
        line_break_idx_range: (usize, usize),
132
0
    ) -> Bytes {
133
0
        let (mut chunk_iter, mut chunk_byte_start, _, _) = Chunks::new_with_range_at_byte(
134
0
            node,
135
0
            at_byte,
136
0
            byte_idx_range,
137
0
            char_idx_range,
138
0
            line_break_idx_range,
139
0
        );
140
141
0
        let cur_chunk = if byte_idx_range.0 == byte_idx_range.1 {
142
0
            ""
143
0
        } else if at_byte < byte_idx_range.1 {
144
0
            chunk_iter.next().unwrap()
145
        } else {
146
0
            let chunk = chunk_iter.prev().unwrap();
147
0
            chunk_iter.next();
148
0
            chunk_byte_start -= chunk.len();
149
0
            chunk
150
        };
151
152
0
        Bytes {
153
0
            chunk_iter: chunk_iter,
154
0
            cur_chunk: cur_chunk.as_bytes(),
155
0
            byte_idx: at_byte - chunk_byte_start,
156
0
            last_call_was_prev_impl: false,
157
0
            bytes_total: byte_idx_range.1 - byte_idx_range.0,
158
0
            bytes_remaining: byte_idx_range.1 - at_byte,
159
0
            is_reversed: false,
160
0
        }
161
0
    }
162
163
    #[inline(always)]
164
0
    pub(crate) fn from_str(text: &str) -> Bytes {
165
0
        Bytes::from_str_at(text, 0)
166
0
    }
167
168
0
    pub(crate) fn from_str_at(text: &str, byte_idx: usize) -> Bytes {
169
0
        let mut chunk_iter = Chunks::from_str(text, false);
170
0
        let cur_chunk = if let Some(chunk) = chunk_iter.next() {
171
0
            chunk
172
        } else {
173
0
            ""
174
        };
175
0
        Bytes {
176
0
            chunk_iter: chunk_iter,
177
0
            cur_chunk: cur_chunk.as_bytes(),
178
0
            byte_idx: byte_idx,
179
0
            last_call_was_prev_impl: false,
180
0
            bytes_total: text.len(),
181
0
            bytes_remaining: text.len() - byte_idx,
182
0
            is_reversed: false,
183
0
        }
184
0
    }
185
186
    /// Reverses the direction of the iterator in-place.
187
    ///
188
    /// In other words, swaps the behavior of [`prev()`](Bytes::prev())
189
    /// and [`next()`](Bytes::next()).
190
    #[inline]
191
0
    pub fn reverse(&mut self) {
192
0
        self.is_reversed = !self.is_reversed;
193
0
    }
194
195
    /// Same as `reverse()`, but returns itself.
196
    ///
197
    /// This is useful when chaining iterator methods:
198
    ///
199
    /// ```rust
200
    /// # use ropey::Rope;
201
    /// # let rope = Rope::from_str("Hello there\n world!\n");
202
    /// // Enumerate the rope's bytes in reverse, starting from the end.
203
    /// for (i, b) in rope.bytes_at(rope.len_bytes()).reversed().enumerate() {
204
    ///     println!("{} {}", i, b);
205
    /// #   assert_eq!(b, rope.byte(rope.len_bytes() - i - 1));
206
    /// }
207
    #[inline]
208
    #[must_use]
209
0
    pub fn reversed(mut self) -> Bytes<'a> {
210
0
        self.reverse();
211
0
        self
212
0
    }
213
214
    /// Advances the iterator backwards and returns the previous value.
215
    ///
216
    /// Runs in amortized O(1) time and worst-case O(log N) time.
217
    #[inline(always)]
218
0
    pub fn prev(&mut self) -> Option<u8> {
219
0
        if !self.is_reversed {
220
0
            self.prev_impl()
221
        } else {
222
0
            self.next_impl()
223
        }
224
0
    }
225
226
    #[inline]
227
0
    fn prev_impl(&mut self) -> Option<u8> {
228
        // Put us back into a "prev" progression.
229
0
        if !self.last_call_was_prev_impl {
230
0
            self.chunk_iter.prev();
231
0
            self.last_call_was_prev_impl = true;
232
0
        }
233
234
        // Progress the chunks iterator back if needed.
235
0
        if self.byte_idx == 0 {
236
0
            if let Some(chunk) = self.chunk_iter.prev() {
237
0
                self.cur_chunk = chunk.as_bytes();
238
0
                self.byte_idx = self.cur_chunk.len();
239
0
            } else {
240
0
                return None;
241
            }
242
0
        }
243
244
        // Progress the byte counts and return the previous byte.
245
0
        self.byte_idx -= 1;
246
0
        self.bytes_remaining += 1;
247
0
        return Some(self.cur_chunk[self.byte_idx]);
248
0
    }
249
250
    #[inline]
251
0
    fn next_impl(&mut self) -> Option<u8> {
252
        // Put us back into a "next" progression.
253
0
        if self.last_call_was_prev_impl {
254
0
            self.chunk_iter.next();
255
0
            self.last_call_was_prev_impl = false;
256
0
        }
257
258
        // Progress the chunks iterator forward if needed.
259
0
        if self.byte_idx >= self.cur_chunk.len() {
260
0
            if let Some(chunk) = self.chunk_iter.next() {
261
0
                self.cur_chunk = chunk.as_bytes();
262
0
                self.byte_idx = 0;
263
0
            } else {
264
0
                return None;
265
            }
266
0
        }
267
268
        // Progress the byte counts and return the next byte.
269
0
        let byte = self.cur_chunk[self.byte_idx];
270
0
        self.byte_idx += 1;
271
0
        self.bytes_remaining -= 1;
272
0
        return Some(byte);
273
0
    }
274
}
275
276
impl<'a> Iterator for Bytes<'a> {
277
    type Item = u8;
278
279
    /// Advances the iterator forward and returns the next value.
280
    ///
281
    /// Runs in amortized O(1) time and worst-case O(log N) time.
282
    #[inline(always)]
283
0
    fn next(&mut self) -> Option<u8> {
284
0
        if !self.is_reversed {
285
0
            self.next_impl()
286
        } else {
287
0
            self.prev_impl()
288
        }
289
0
    }
290
291
0
    fn size_hint(&self) -> (usize, Option<usize>) {
292
0
        let remaining = if !self.is_reversed {
293
0
            self.bytes_remaining
294
        } else {
295
0
            self.bytes_total - self.bytes_remaining
296
        };
297
0
        (remaining, Some(remaining))
298
0
    }
299
}
300
301
impl<'a> ExactSizeIterator for Bytes<'a> {}
302
303
//==========================================================
304
305
/// An iterator over a `Rope`'s chars.
306
#[derive(Debug, Clone)]
307
pub struct Chars<'a> {
308
    chunk_iter: Chunks<'a>,
309
    cur_chunk: &'a str,
310
    byte_idx: usize,
311
    last_call_was_prev_impl: bool,
312
    chars_total: usize,
313
    chars_remaining: usize,
314
    is_reversed: bool,
315
}
316
317
impl<'a> Chars<'a> {
318
0
    pub(crate) fn new(node: &Arc<Node>) -> Chars {
319
0
        let mut chunk_iter = Chunks::new(node);
320
0
        let cur_chunk = if let Some(chunk) = chunk_iter.next() {
321
0
            chunk
322
        } else {
323
0
            ""
324
        };
325
0
        Chars {
326
0
            chunk_iter: chunk_iter,
327
0
            cur_chunk: cur_chunk,
328
0
            byte_idx: 0,
329
0
            last_call_was_prev_impl: false,
330
0
            chars_total: node.text_info().chars as usize,
331
0
            chars_remaining: node.text_info().chars as usize,
332
0
            is_reversed: false,
333
0
        }
334
0
    }
335
336
    #[inline(always)]
337
0
    pub(crate) fn new_with_range(
338
0
        node: &Arc<Node>,
339
0
        byte_idx_range: (usize, usize),
340
0
        char_idx_range: (usize, usize),
341
0
        line_break_idx_range: (usize, usize),
342
0
    ) -> Chars {
343
0
        Chars::new_with_range_at(
344
0
            node,
345
0
            char_idx_range.0,
346
0
            byte_idx_range,
347
0
            char_idx_range,
348
0
            line_break_idx_range,
349
        )
350
0
    }
351
352
0
    pub(crate) fn new_with_range_at(
353
0
        node: &Arc<Node>,
354
0
        at_char: usize,
355
0
        byte_idx_range: (usize, usize),
356
0
        char_idx_range: (usize, usize),
357
0
        line_break_idx_range: (usize, usize),
358
0
    ) -> Chars {
359
0
        let (mut chunk_iter, _, mut chunk_char_start, _) = Chunks::new_with_range_at_char(
360
0
            node,
361
0
            at_char,
362
0
            byte_idx_range,
363
0
            char_idx_range,
364
0
            line_break_idx_range,
365
0
        );
366
367
0
        let cur_chunk = if char_idx_range.0 == char_idx_range.1 {
368
0
            ""
369
0
        } else if at_char < char_idx_range.1 {
370
0
            chunk_iter.next().unwrap()
371
        } else {
372
0
            let chunk = chunk_iter.prev().unwrap();
373
0
            chunk_iter.next();
374
0
            chunk_char_start =
375
0
                (node.get_chunk_at_char(at_char - 1).1.chars as usize).max(char_idx_range.0);
376
0
            chunk
377
        };
378
379
0
        Chars {
380
0
            chunk_iter: chunk_iter,
381
0
            cur_chunk: cur_chunk,
382
0
            byte_idx: char_to_byte_idx(cur_chunk, at_char - chunk_char_start),
383
0
            last_call_was_prev_impl: false,
384
0
            chars_total: char_idx_range.1 - char_idx_range.0,
385
0
            chars_remaining: char_idx_range.1 - at_char,
386
0
            is_reversed: false,
387
0
        }
388
0
    }
389
390
    #[inline(always)]
391
0
    pub(crate) fn from_str(text: &str) -> Chars {
392
0
        Chars::from_str_at(text, 0)
393
0
    }
394
395
0
    pub(crate) fn from_str_at(text: &str, char_idx: usize) -> Chars {
396
0
        let mut chunk_iter = Chunks::from_str(text, false);
397
0
        let cur_chunk = if let Some(chunk) = chunk_iter.next() {
398
0
            chunk
399
        } else {
400
0
            ""
401
        };
402
0
        let start_byte_idx = char_to_byte_idx(text, char_idx);
403
0
        let chars_remaining = count_chars(&text[start_byte_idx..]);
404
405
0
        Chars {
406
0
            chunk_iter: chunk_iter,
407
0
            cur_chunk: cur_chunk,
408
0
            byte_idx: start_byte_idx,
409
0
            last_call_was_prev_impl: false,
410
0
            chars_total: chars_remaining + count_chars(&text[..start_byte_idx]),
411
0
            chars_remaining: chars_remaining,
412
0
            is_reversed: false,
413
0
        }
414
0
    }
415
416
    /// Reverses the direction of the iterator in-place.
417
    ///
418
    /// In other words, swaps the behavior of [`prev()`](Chars::prev())
419
    /// and [`next()`](Chars::next()).
420
    #[inline]
421
0
    pub fn reverse(&mut self) {
422
0
        self.is_reversed = !self.is_reversed;
423
0
    }
424
425
    /// Same as `reverse()`, but returns itself.
426
    ///
427
    /// This is useful when chaining iterator methods:
428
    ///
429
    /// ```rust
430
    /// # use ropey::Rope;
431
    /// # let rope = Rope::from_str("Hello there\n world!\n");
432
    /// // Enumerate the rope's chars in reverse, starting from the end.
433
    /// for (i, ch) in rope.chars_at(rope.len_chars()).reversed().enumerate() {
434
    ///     println!("{} {}", i, ch);
435
    /// #   assert_eq!(ch, rope.char(rope.len_chars() - i - 1));
436
    /// }
437
    #[inline]
438
    #[must_use]
439
0
    pub fn reversed(mut self) -> Chars<'a> {
440
0
        self.reverse();
441
0
        self
442
0
    }
443
444
    /// Advances the iterator backwards and returns the previous value.
445
    ///
446
    /// Runs in amortized O(1) time and worst-case O(log N) time.
447
    #[inline(always)]
448
0
    pub fn prev(&mut self) -> Option<char> {
449
0
        if !self.is_reversed {
450
0
            self.prev_impl()
451
        } else {
452
0
            self.next_impl()
453
        }
454
0
    }
455
456
    #[inline]
457
0
    fn prev_impl(&mut self) -> Option<char> {
458
        // Put us back into a "prev" progression.
459
0
        if !self.last_call_was_prev_impl {
460
0
            self.chunk_iter.prev();
461
0
            self.last_call_was_prev_impl = true;
462
0
        }
463
464
        // Progress the chunks iterator back if needed.
465
0
        if self.byte_idx == 0 {
466
0
            if let Some(chunk) = self.chunk_iter.prev() {
467
0
                self.cur_chunk = chunk;
468
0
                self.byte_idx = self.cur_chunk.len();
469
0
            } else {
470
0
                return None;
471
            }
472
0
        }
473
474
        // Find the previous char boundary, updating counters as needed, and
475
        // return the previous char.
476
0
        self.byte_idx -= 1;
477
0
        while !self.cur_chunk.is_char_boundary(self.byte_idx) {
478
0
            self.byte_idx -= 1;
479
0
        }
480
0
        self.chars_remaining += 1;
481
0
        return (&self.cur_chunk[self.byte_idx..]).chars().next();
482
0
    }
Unexecuted instantiation: <ropey::iter::Chars>::prev_impl
Unexecuted instantiation: <ropey::iter::Chars>::prev_impl
483
484
    #[inline]
485
0
    fn next_impl(&mut self) -> Option<char> {
486
        // Put us back into a "next" progression.
487
0
        if self.last_call_was_prev_impl {
488
0
            self.chunk_iter.next();
489
0
            self.last_call_was_prev_impl = false;
490
0
        }
491
492
        // Progress the chunks iterator forward if needed.
493
0
        if self.byte_idx >= self.cur_chunk.len() {
494
0
            if let Some(chunk) = self.chunk_iter.next() {
495
0
                self.cur_chunk = chunk;
496
0
                self.byte_idx = 0;
497
0
            } else {
498
0
                return None;
499
            }
500
0
        }
501
502
        // Find the next char boundary, updating counters as needed, and
503
        // return the next char.
504
0
        let start = self.byte_idx;
505
0
        self.byte_idx += 1;
506
0
        while !self.cur_chunk.is_char_boundary(self.byte_idx) {
507
0
            self.byte_idx += 1;
508
0
        }
509
0
        self.chars_remaining -= 1;
510
0
        return (&self.cur_chunk[start..]).chars().next();
511
0
    }
Unexecuted instantiation: <ropey::iter::Chars>::next_impl
Unexecuted instantiation: <ropey::iter::Chars>::next_impl
512
}
513
514
impl<'a> Iterator for Chars<'a> {
515
    type Item = char;
516
517
    /// Advances the iterator forward and returns the next value.
518
    ///
519
    /// Runs in amortized O(1) time and worst-case O(log N) time.
520
    #[inline(always)]
521
0
    fn next(&mut self) -> Option<char> {
522
0
        if !self.is_reversed {
523
0
            self.next_impl()
524
        } else {
525
0
            self.prev_impl()
526
        }
527
0
    }
528
529
0
    fn size_hint(&self) -> (usize, Option<usize>) {
530
0
        let remaining = if !self.is_reversed {
531
0
            self.chars_remaining
532
        } else {
533
0
            self.chars_total - self.chars_remaining
534
        };
535
0
        (remaining, Some(remaining))
536
0
    }
537
}
538
539
impl<'a> ExactSizeIterator for Chars<'a> {}
540
541
//==========================================================
542
543
/// An iterator over a `Rope`'s lines.
544
///
545
/// The returned lines include the line break at the end, if any.
546
///
547
/// The last line is returned even if blank, in which case it
548
/// is returned as an empty slice.
549
#[derive(Debug, Clone)]
550
pub struct Lines<'a> {
551
    iter: LinesEnum<'a>,
552
    is_reversed: bool,
553
    /// The content of the current tree leaf.
554
    text: &'a str,
555
    /// The total byte position of the iterator.
556
    byte_idx: usize,
557
    at_end: bool,
558
    line_idx: usize,
559
    total_lines: usize,
560
}
561
562
#[derive(Debug, Clone)]
563
enum LinesEnum<'a> {
564
    Full {
565
        /// A stack of nodes that represents the current tree position.
566
        /// This stack contains only internal nodes, the leaf text is
567
        /// stored in the `Lines::text` field instead.
568
        /// Each entry contains a tree node and the index of the current
569
        /// child that is stored next on the stack (or the index of the
570
        /// leaf) for the last node.
571
        node_stack: Vec<(&'a Arc<Node>, usize)>,
572
        /// The position within the current leaf (`Lines::text`).
573
        leaf_byte_idx: u32,
574
        /// The total number of bytes this iterator can traverse.
575
        total_bytes: usize,
576
    },
577
    Light,
578
}
579
580
impl<'a> Lines<'a> {
581
    #[inline(always)]
582
0
    pub(crate) fn new(node: &Arc<Node>) -> Lines {
583
0
        let info = node.text_info();
584
0
        Lines::new_with_range_at(
585
0
            node,
586
            0,
587
0
            (0, info.bytes as usize),
588
0
            (0, info.line_breaks as usize + 1),
589
        )
590
0
    }
591
592
    #[inline(always)]
593
0
    pub(crate) fn new_with_range(
594
0
        node: &Arc<Node>,
595
0
        byte_idx_range: (usize, usize),
596
0
        line_idx_range: (usize, usize),
597
0
    ) -> Lines {
598
0
        Lines::new_with_range_at(node, line_idx_range.0, byte_idx_range, line_idx_range)
599
0
    }
600
601
0
    pub(crate) fn new_with_range_at(
602
0
        node: &Arc<Node>,
603
0
        line: usize,
604
0
        byte_idx_range: (usize, usize),
605
0
        line_idx_range: (usize, usize),
606
0
    ) -> Lines {
607
0
        debug_assert!(node.is_char_boundary(byte_idx_range.0));
608
0
        debug_assert!(node.is_char_boundary(byte_idx_range.1));
609
0
        debug_assert!(line >= line_idx_range.0);
610
611
        // For convenience/readability.
612
0
        let total_lines = line_idx_range.1 - line_idx_range.0;
613
614
        // Special-case: empty slice/rope.
615
0
        if byte_idx_range.0 == byte_idx_range.1 {
616
0
            return Lines {
617
0
                iter: LinesEnum::Light,
618
0
                text: "",
619
0
                at_end: false,
620
0
                is_reversed: false,
621
0
                byte_idx: 0,
622
0
                line_idx: 0,
623
0
                total_lines: 1,
624
0
            };
625
0
        }
626
627
        // Special-case: root is a leaf.  Return light version of the iterator.
628
0
        if node.is_leaf() {
629
0
            let text = &node.leaf_text()[byte_idx_range.0..byte_idx_range.1];
630
0
            return Lines::from_str_at(text, line - line_idx_range.0, total_lines);
631
0
        }
632
633
        // Common case.  Traverse into the tree to build the iterator.
634
0
        let mut start_byte_idx = byte_idx_range.0;
635
0
        let mut end_byte_idx = byte_idx_range.1;
636
0
        let mut line_idx = line;
637
0
        let mut chunk_byte_start = 0;
638
0
        let mut node_stack: Vec<(&Arc<Node>, usize)> = Vec::new();
639
0
        let mut node_ref = node;
640
        loop {
641
0
            match **node_ref {
642
                // Recursively traverse into whichever child has the target line break,
643
                // bounded by the start and end bytes of the slice/rope.
644
0
                Node::Internal(ref children) => {
645
                    // Find the appropriate child.
646
0
                    let (child_i, acc) = children.search_by(|_, end_info| {
647
0
                        if (end_info.bytes as usize) >= end_byte_idx {
648
0
                            true
649
0
                        } else if line_idx <= (end_info.line_breaks as usize) {
650
0
                            (end_info.bytes as usize) > start_byte_idx
651
                        } else {
652
0
                            false
653
                        }
654
0
                    });
655
656
                    // Update tracking info.
657
0
                    start_byte_idx = start_byte_idx.saturating_sub(acc.bytes as usize);
658
0
                    end_byte_idx -= acc.bytes as usize;
659
0
                    line_idx -= acc.line_breaks as usize;
660
0
                    chunk_byte_start += acc.bytes as usize;
661
662
                    // Add to the node stack.
663
0
                    node_stack.push((node_ref, child_i));
664
0
                    node_ref = &children.nodes()[child_i];
665
                }
666
667
                // Create the iterator.
668
0
                Node::Leaf(ref text) => {
669
0
                    let leaf_byte_idx = line_to_byte_idx(text, line_idx)
670
0
                        .max(start_byte_idx)
671
0
                        .min(end_byte_idx);
672
673
0
                    let res = Lines {
674
0
                        iter: LinesEnum::Full {
675
0
                            node_stack,
676
0
                            leaf_byte_idx: leaf_byte_idx as u32,
677
0
                            total_bytes: byte_idx_range.1 - byte_idx_range.0,
678
0
                        },
679
                        is_reversed: false,
680
0
                        text,
681
0
                        byte_idx: chunk_byte_start + leaf_byte_idx - byte_idx_range.0,
682
0
                        at_end: leaf_byte_idx == end_byte_idx
683
0
                            && line_idx > byte_to_line_idx(&text[..end_byte_idx], end_byte_idx),
684
0
                        line_idx: line - line_idx_range.0,
685
0
                        total_lines,
686
                    };
687
688
0
                    return res;
689
                }
690
            }
691
        }
692
0
    }
693
694
    /// NOT PART OF THE PUBLIC API (hidden from docs for a reason!).
695
    ///
696
    /// This is only exposed publicly for use in property testing.
697
    #[doc(hidden)]
698
0
    pub fn from_str_pt(text: &str) -> Lines {
699
0
        let line_count = byte_to_line_idx(text, text.len()) + 1;
700
0
        Lines::from_str(text, line_count)
701
0
    }
702
703
0
    pub(crate) fn from_str(text: &str, lines: usize) -> Lines {
704
0
        Lines {
705
0
            iter: LinesEnum::Light,
706
0
            is_reversed: false,
707
0
            text: text,
708
0
            byte_idx: 0,
709
0
            at_end: false,
710
0
            line_idx: 0,
711
0
            total_lines: lines,
712
0
        }
713
0
    }
714
715
0
    pub(crate) fn from_str_at(text: &str, line: usize, lines: usize) -> Lines {
716
0
        Lines {
717
0
            iter: LinesEnum::Light,
718
0
            is_reversed: false,
719
0
            text: text,
720
0
            byte_idx: line_to_byte_idx(text, line),
721
0
            at_end: line >= lines,
722
0
            line_idx: line.min(lines),
723
0
            total_lines: lines,
724
0
        }
725
0
    }
726
    /// Reverses the direction of the iterator in-place.
727
    ///
728
    /// In other words, swaps the behavior of [`prev()`](Lines::prev())
729
    /// and [`next()`](Lines::next()).
730
    #[inline]
731
0
    pub fn reverse(&mut self) {
732
0
        self.is_reversed = !self.is_reversed;
733
0
    }
734
735
    /// Same as `reverse()`, but returns itself.
736
    ///
737
    /// This is useful when chaining iterator methods:
738
    ///
739
    /// ```rust
740
    /// # use ropey::Rope;
741
    /// # let rope = Rope::from_str("Hello there\n world!\n");
742
    /// // Enumerate the rope's lines in reverse, starting from the end.
743
    /// for (i, line) in rope.lines_at(rope.len_lines()).reversed().enumerate() {
744
    ///     println!("{} {}", i, line);
745
    /// #   assert_eq!(line, rope.line(rope.len_lines() - i - 1));
746
    /// }
747
    #[inline]
748
    #[must_use]
749
0
    pub fn reversed(mut self) -> Lines<'a> {
750
0
        self.reverse();
751
0
        self
752
0
    }
753
754
    /// Advances the iterator backwards and returns the previous value.
755
    ///
756
    /// Runs in O(1) time with respect to rope length and O(N) time with
757
    /// respect to line length.
758
    #[inline(always)]
759
0
    pub fn prev(&mut self) -> Option<RopeSlice<'a>> {
760
0
        if self.is_reversed {
761
0
            self.next_impl()
762
        } else {
763
0
            self.prev_impl()
764
        }
765
0
    }
766
767
0
    fn prev_impl(&mut self) -> Option<RopeSlice<'a>> {
768
0
        match *self {
769
            Lines {
770
                iter:
771
                    LinesEnum::Full {
772
0
                        ref mut node_stack,
773
0
                        ref mut leaf_byte_idx,
774
                        ..
775
                    },
776
0
                ref mut byte_idx,
777
0
                ref mut text,
778
0
                ref mut at_end,
779
0
                ref mut line_idx,
780
                ..
781
            } => {
782
0
                let tail = &text[..*leaf_byte_idx as usize];
783
784
                // The only line yielded by this iterator that doesn't
785
                // end with a line break is the very last line. As the
786
                // very last line requires a special conditon here
787
                // anyway we can save the result so we don't have to
788
                // count newlines later.
789
0
                let ends_with_line_break = if std::mem::take(at_end) {
790
0
                    if ends_with_line_break(tail) {
791
0
                        *line_idx -= 1;
792
0
                        return Some(RopeSlice(RSEnum::Light {
793
0
                            text: "",
794
0
                            char_count: 0,
795
0
                            utf16_surrogate_count: 0,
796
0
                            line_break_count: 0,
797
0
                        }));
798
0
                    }
799
0
                    false
800
0
                } else if *byte_idx == 0 {
801
0
                    return None;
802
                } else {
803
0
                    true
804
                };
805
806
0
                *line_idx -= 1;
807
808
                // Get the byte index of the start of the line within the chunk,
809
                // and whether we know if the line is contained entirely within
810
                // the chunk or not.
811
0
                let (line_start_idx, line_inside_chunk) = {
812
0
                    let line_start = last_line_start_byte_idx(trim_line_break(tail));
813
0
                    let line_len = *leaf_byte_idx as usize - line_start;
814
0
                    if line_len >= *byte_idx {
815
0
                        (*leaf_byte_idx as usize - *byte_idx, true)
816
                    } else {
817
0
                        (line_start, line_start > 0)
818
                    }
819
                };
820
821
0
                let chunk_line = &tail[line_start_idx..];
822
0
                *byte_idx -= chunk_line.len();
823
824
                // If the line is contained entirely within the current chunk, return it.
825
0
                if line_inside_chunk {
826
0
                    *leaf_byte_idx = line_start_idx as u32;
827
0
                    return Some(RopeSlice(RSEnum::Light {
828
0
                        text: chunk_line,
829
0
                        char_count: count_chars(chunk_line) as Count,
830
0
                        utf16_surrogate_count: count_utf16_surrogates(chunk_line) as Count,
831
0
                        line_break_count: ends_with_line_break as Count,
832
0
                    }));
833
0
                }
834
835
                // We need to advance to the next (preceding) chunk that contains
836
                // a line break.  As the line might span across multiple chunks we
837
                // track the closest common parent node (and position within that
838
                // node) during traversal to avoid expensive `RopeSlice` construction
839
                // later.
840
0
                let mut shared_parent = node_stack.len() - 1;
841
0
                let mut pos_in_shared_parent = {
842
0
                    let (parent, child_i) = *node_stack.last().unwrap();
843
0
                    parent.children().info()[..child_i]
844
0
                        .iter()
845
0
                        .fold(TextInfo::new(), |res, it| res + *it)
846
                };
847
0
                let mut len = TextInfo::from_str(tail);
848
0
                pos_in_shared_parent += len;
849
850
                // If the line starts exactly at the start of the chunk
851
                // then it might not actually span multiple chunks.
852
0
                let mut multi_chunk_slice = !tail.is_empty();
853
0
                let head_start = loop {
854
0
                    let mut stack_idx = node_stack.len() - 1;
855
0
                    let (_, child_i) = node_stack.last_mut().unwrap();
856
857
                    // If the iterator has reached the start of the parent node, advance
858
                    // to the previous parent.
859
0
                    if *child_i == 0 {
860
                        // Find how high up the stack we need to go to advance to
861
                        // the previous chunk.
862
0
                        while node_stack[stack_idx].1 == 0 {
863
0
                            debug_assert_ne!(stack_idx, 0, "iterated past the first leaf");
864
0
                            stack_idx -= 1;
865
                        }
866
867
                        // If we've reached a new high position in the stack, accumulate its
868
                        // TextInfo for `RopeSlice` construction later.
869
0
                        if stack_idx < shared_parent {
870
0
                            for (node, child_i) in &node_stack[stack_idx..shared_parent] {
871
0
                                for &child_pos in &node.children().info()[..*child_i] {
872
0
                                    pos_in_shared_parent += child_pos;
873
0
                                }
874
                            }
875
0
                            shared_parent = stack_idx;
876
0
                        }
877
878
                        // Advance to the previous chunk.
879
0
                        node_stack[stack_idx].1 -= 1;
880
0
                        while stack_idx < (node_stack.len() - 1) {
881
0
                            let child_i = node_stack[stack_idx].1;
882
0
                            let node = &node_stack[stack_idx].0.children().nodes()[child_i];
883
0
                            node_stack[stack_idx + 1] = (node, node.child_count() - 1);
884
0
                            stack_idx += 1;
885
0
                        }
886
0
                    } else {
887
0
                        // Advance to the previous sibling chunk.
888
0
                        *child_i -= 1;
889
0
                    }
890
891
0
                    let (node, child_i) = *node_stack.last().unwrap();
892
0
                    let info = node.children().info()[child_i];
893
0
                    let available_bytes = *byte_idx;
894
895
0
                    if info.line_breaks != 0 {
896
                        // This chunk contains a line break so it will contain the start of our line.
897
0
                        *text = node.children().nodes()[child_i].leaf_text();
898
                        // Find the start of the line within the chunk.
899
                        // The function used here is slightly different because it must
900
                        // not skip the first line break.
901
                        // A line break at the end of the chunk is already the line break
902
                        // we are looking for.  The line break belonging to this line is
903
                        // always contained in the chunk we started this iteration at.
904
0
                        let mut line_start = last_line_start_byte_idx(text);
905
                        // Cut off the line at the start of the iterator.
906
0
                        let line_len = text.len() - line_start;
907
0
                        if line_len >= available_bytes {
908
0
                            line_start = text.len() - available_bytes;
909
0
                        }
910
0
                        break line_start;
911
0
                    }
912
913
0
                    if info.bytes as usize >= available_bytes {
914
                        // This chunk does not contain a line break but the current
915
                        // line still ends here because the iterator is exhaused.
916
0
                        *text = node.children().nodes()[child_i].leaf_text();
917
0
                        break text.len() - *byte_idx;
918
0
                    }
919
920
0
                    len += info;
921
0
                    *byte_idx -= info.bytes as usize;
922
0
                    multi_chunk_slice = true;
923
                };
924
0
                let head = &text[head_start..];
925
926
                // Book keeping.
927
0
                *byte_idx -= head.len();
928
0
                *leaf_byte_idx = head_start as u32;
929
930
                // Construct the `RopeSlice` containing the line.
931
                // Note that `head` never contains any line breaks because the
932
                // iterator stops at the first line break (see comment above).
933
0
                let head_chars = count_chars(head) as Count;
934
0
                let head_surrogates = count_utf16_surrogates(head) as Count;
935
0
                let line = if multi_chunk_slice {
936
0
                    RSEnum::Full {
937
0
                        node: node_stack[shared_parent].0,
938
0
                        start_info: pos_in_shared_parent
939
0
                            - TextInfo {
940
0
                                bytes: head.len() as Count,
941
0
                                chars: head_chars,
942
0
                                utf16_surrogates: head_surrogates,
943
0
                                line_breaks: 0,
944
0
                            }
945
0
                            - len,
946
0
                        end_info: pos_in_shared_parent,
947
0
                    }
948
                } else {
949
0
                    RSEnum::Light {
950
0
                        text: head,
951
0
                        char_count: head_chars,
952
0
                        utf16_surrogate_count: head_surrogates,
953
0
                        line_break_count: 0,
954
0
                    }
955
                };
956
0
                let line = RopeSlice(line);
957
958
0
                Some(line)
959
            }
960
961
            Lines {
962
                iter: LinesEnum::Light,
963
0
                ref mut text,
964
0
                ref mut byte_idx,
965
0
                ref mut at_end,
966
0
                ref mut line_idx,
967
                ..
968
            } => {
969
0
                if std::mem::take(at_end) {
970
0
                    if text.is_empty() || ends_with_line_break(text) {
971
0
                        *line_idx -= 1;
972
0
                        return Some("".into());
973
0
                    }
974
0
                } else if *byte_idx == 0 {
975
0
                    return None;
976
0
                }
977
978
0
                let end_idx = *byte_idx;
979
0
                let start_idx = last_line_start_byte_idx(trim_line_break(&text[..end_idx]));
980
0
                *byte_idx = start_idx;
981
0
                *line_idx -= 1;
982
0
                let line = &text[start_idx..end_idx];
983
984
0
                return Some(RopeSlice(RSEnum::Light {
985
0
                    text: line,
986
0
                    char_count: count_chars(line) as Count,
987
0
                    utf16_surrogate_count: count_utf16_surrogates(line) as Count,
988
0
                    line_break_count: 1,
989
0
                }));
990
            }
991
        }
992
0
    }
993
994
0
    fn next_impl(&mut self) -> Option<RopeSlice<'a>> {
995
0
        match *self {
996
            Lines {
997
                iter:
998
                    LinesEnum::Full {
999
0
                        ref mut node_stack,
1000
0
                        ref mut leaf_byte_idx,
1001
0
                        total_bytes,
1002
                    },
1003
0
                ref mut byte_idx,
1004
0
                ref mut text,
1005
0
                ref mut at_end,
1006
0
                ref mut line_idx,
1007
                ..
1008
            } => {
1009
0
                if *at_end {
1010
0
                    return None;
1011
0
                } else if *byte_idx == total_bytes {
1012
0
                    *at_end = true;
1013
0
                    *line_idx += 1;
1014
0
                    return Some(RopeSlice(RSEnum::Light {
1015
0
                        text: "",
1016
0
                        char_count: 0,
1017
0
                        utf16_surrogate_count: 0,
1018
0
                        line_break_count: 0,
1019
0
                    }));
1020
0
                }
1021
0
                *line_idx += 1;
1022
1023
0
                let head = &text[*leaf_byte_idx as usize..];
1024
0
                let mut line_len = line_to_byte_idx(head, 1);
1025
1026
                // Check if the iterators needs to advance to the next chunk.
1027
                // During this check the number of newline (0 or 1) is yielded
1028
                // for free so save that aswell.
1029
0
                let available_bytes = total_bytes - *byte_idx;
1030
0
                let (line_inside_chunk, line_break_count) = if line_len >= available_bytes {
1031
                    // If the iterator is exhausted we don't need to switch chunks.
1032
                    // Check if the last line has a line break to decide whether
1033
                    // we still need to yield an empty line later.
1034
0
                    line_len = available_bytes;
1035
0
                    let ends_with_line_break = ends_with_line_break(&head[..line_len]);
1036
0
                    *at_end = !ends_with_line_break;
1037
                    // Reached end of the text, so no need to advance.
1038
0
                    (true, ends_with_line_break as u64)
1039
                } else {
1040
                    // Iterator is not yet exhausted, so advance to the next chunk
1041
                    // if we've reached the chunk boundary and the last character
1042
                    // is not a line break.  If the iterator is not exhausted, a
1043
                    // line always ends with a line break.
1044
0
                    (line_len != head.len() || ends_with_line_break(head), 1)
1045
                };
1046
1047
                // Yield the current line if it is contained within the current chunk.
1048
0
                if line_inside_chunk {
1049
0
                    let line = &head[..line_len];
1050
0
                    *byte_idx += line_len;
1051
0
                    *leaf_byte_idx += line_len as u32;
1052
1053
0
                    return Some(RopeSlice(RSEnum::Light {
1054
0
                        text: line,
1055
0
                        char_count: count_chars(line) as Count,
1056
0
                        utf16_surrogate_count: count_utf16_surrogates(line) as Count,
1057
0
                        line_break_count,
1058
0
                    }));
1059
0
                }
1060
1061
0
                *byte_idx += head.len();
1062
1063
                // We need to advance to the next chunk that contains
1064
                // a line break.  As the line might span across multiple chunks we
1065
                // track the closest common parent node (and position within that
1066
                // node) during traversal to avoid expensive `RopeSlice` construction
1067
                // later.
1068
0
                let mut shared_parent = node_stack.len() - 1;
1069
0
                let mut pos_in_shared_parent = {
1070
0
                    let (parent, child_i) = *node_stack.last().unwrap();
1071
0
                    parent.children().info()[..=child_i]
1072
0
                        .iter()
1073
0
                        .fold(TextInfo::new(), |res, it| res + *it)
1074
                };
1075
0
                let mut len = TextInfo::from_str(head);
1076
0
                pos_in_shared_parent -= len;
1077
1078
                // If the line starts exactly at the start of the next chunk
1079
                // then it might not actually span multiple chunks.
1080
0
                let mut multi_chunk_slice = !head.is_empty();
1081
0
                let (tail_len, tail_ends_with_newline) = loop {
1082
0
                    let mut stack_idx = node_stack.len() - 1;
1083
1084
                    // Advance to the next sibling chunk.
1085
0
                    let (_, child_i) = node_stack.last_mut().unwrap();
1086
0
                    *child_i += 1;
1087
1088
                    // If the iterator has reached the end of the parent node, advance
1089
                    // to the next parent.
1090
0
                    if *child_i >= node_stack[stack_idx].0.child_count() {
1091
                        // Find how high up the stack we need to go to advance to
1092
                        // the next chunk.
1093
0
                        while node_stack[stack_idx].1 >= (node_stack[stack_idx].0.child_count() - 1)
1094
                        {
1095
0
                            debug_assert_ne!(stack_idx, 0, "iterated past the last leaf");
1096
0
                            stack_idx -= 1;
1097
                        }
1098
1099
                        // If we've reached a new high position in the stack, accumulate its
1100
                        // TextInfo for `RopeSlice` construction later.
1101
0
                        if stack_idx < shared_parent {
1102
0
                            for (node, child_i) in &node_stack[stack_idx..shared_parent] {
1103
0
                                for &child_pos in &node.children().info()[..*child_i] {
1104
0
                                    pos_in_shared_parent += child_pos;
1105
0
                                }
1106
                            }
1107
0
                            shared_parent = stack_idx;
1108
0
                        }
1109
1110
                        // Advance to the next chunk.
1111
0
                        node_stack[stack_idx].1 += 1;
1112
0
                        while stack_idx < (node_stack.len() - 1) {
1113
0
                            let child_i = node_stack[stack_idx].1;
1114
0
                            let node = &node_stack[stack_idx].0.children().nodes()[child_i];
1115
0
                            node_stack[stack_idx + 1] = (node, 0);
1116
0
                            stack_idx += 1;
1117
0
                        }
1118
0
                    }
1119
1120
0
                    let (node, child_i) = *node_stack.last().unwrap();
1121
0
                    let info = node.children().info()[child_i];
1122
0
                    let available_bytes = total_bytes - *byte_idx;
1123
1124
0
                    if info.line_breaks != 0 {
1125
                        // This chunk contains a line break so it will contain the start of our line.
1126
0
                        *text = node.children().nodes()[child_i].leaf_text();
1127
                        // Find the end of the line within the chunk.
1128
0
                        let mut line_end = line_to_byte_idx(text, 1);
1129
                        // Check if the iterator was exhausted.
1130
0
                        let ends_with_newline = if line_end >= available_bytes {
1131
                            // Handle terminating lines without a line break properly.
1132
0
                            line_end = available_bytes;
1133
0
                            let ends_with_newline = ends_with_line_break(&text[..line_end]);
1134
0
                            *at_end = !ends_with_newline;
1135
0
                            ends_with_newline
1136
                        } else {
1137
0
                            true
1138
                        };
1139
0
                        break (line_end, ends_with_newline);
1140
0
                    }
1141
1142
0
                    if info.bytes as usize >= available_bytes {
1143
                        // This chunk does not contain a line break but the current
1144
                        // line still ends here because the iterator is exhausted.
1145
0
                        *at_end = true;
1146
0
                        *text = node.children().nodes()[child_i].leaf_text();
1147
0
                        break (available_bytes, false);
1148
0
                    }
1149
1150
0
                    len += info;
1151
0
                    *byte_idx += info.bytes as usize;
1152
0
                    multi_chunk_slice = true;
1153
                };
1154
1155
                // Book keeping.
1156
0
                *byte_idx += tail_len;
1157
0
                *leaf_byte_idx = tail_len as u32;
1158
1159
                // Construct the `RopeSlice` containing the line.
1160
0
                let line_tail = &text[..tail_len];
1161
0
                let line_tail_chars = count_chars(line_tail) as Count;
1162
0
                let line_tail_surrogates = count_utf16_surrogates(line_tail) as Count;
1163
0
                let line = if multi_chunk_slice {
1164
0
                    RSEnum::Full {
1165
0
                        node: node_stack[shared_parent].0,
1166
0
                        start_info: pos_in_shared_parent,
1167
0
                        end_info: pos_in_shared_parent
1168
0
                            + len
1169
0
                            + TextInfo {
1170
0
                                bytes: tail_len as Count,
1171
0
                                chars: line_tail_chars,
1172
0
                                utf16_surrogates: line_tail_surrogates,
1173
0
                                line_breaks: tail_ends_with_newline as Count,
1174
0
                            },
1175
0
                    }
1176
                } else {
1177
0
                    RSEnum::Light {
1178
0
                        text: line_tail,
1179
0
                        char_count: line_tail_chars,
1180
0
                        utf16_surrogate_count: line_tail_surrogates,
1181
0
                        line_break_count: tail_ends_with_newline as Count,
1182
0
                    }
1183
                };
1184
1185
0
                Some(RopeSlice(line))
1186
            }
1187
1188
            Lines {
1189
                iter: LinesEnum::Light,
1190
0
                text,
1191
0
                ref mut byte_idx,
1192
0
                ref mut at_end,
1193
0
                ref mut line_idx,
1194
                ..
1195
            } => {
1196
0
                if *at_end {
1197
0
                    return None;
1198
0
                } else if *byte_idx == text.len() {
1199
0
                    *at_end = true;
1200
0
                    *line_idx += 1;
1201
0
                    return Some("".into());
1202
0
                }
1203
1204
0
                let start_idx = *byte_idx;
1205
0
                let end_idx = line_to_byte_idx(&text[start_idx..], 1) + start_idx;
1206
0
                *byte_idx = end_idx;
1207
0
                *line_idx += 1;
1208
1209
0
                if end_idx == text.len() {
1210
0
                    *at_end = !ends_with_line_break(text);
1211
0
                }
1212
1213
0
                return Some((&text[start_idx..end_idx]).into());
1214
            }
1215
        }
1216
0
    }
1217
}
1218
1219
impl<'a> Iterator for Lines<'a> {
1220
    type Item = RopeSlice<'a>;
1221
1222
    /// Advances the iterator forward and returns the next value.
1223
    ///
1224
    /// Runs in O(1) time with respect to rope length and O(N) time with
1225
    /// respect to line length.
1226
    #[inline(always)]
1227
0
    fn next(&mut self) -> Option<RopeSlice<'a>> {
1228
0
        if self.is_reversed {
1229
0
            self.prev_impl()
1230
        } else {
1231
0
            self.next_impl()
1232
        }
1233
0
    }
1234
1235
0
    fn size_hint(&self) -> (usize, Option<usize>) {
1236
0
        if self.is_reversed {
1237
0
            (self.line_idx, Some(self.line_idx))
1238
        } else {
1239
0
            (
1240
0
                self.total_lines - self.line_idx,
1241
0
                Some(self.total_lines - self.line_idx),
1242
0
            )
1243
        }
1244
0
    }
1245
}
1246
1247
impl ExactSizeIterator for Lines<'_> {}
1248
1249
//==========================================================
1250
1251
/// An iterator over a `Rope`'s contiguous `str` chunks.
1252
///
1253
/// Internally, each `Rope` stores text as a segemented collection of utf8
1254
/// strings. This iterator iterates over those segments, returning a
1255
/// `&str` slice for each one.  It is useful for situations such as:
1256
///
1257
/// - Writing a rope's utf8 text data to disk (but see
1258
///   [`write_to()`](crate::rope::Rope::write_to) for a convenience function that does this
1259
///   for casual use-cases).
1260
/// - Streaming a rope's text data somewhere.
1261
/// - Saving a rope to a non-utf8 encoding, doing the encoding conversion
1262
///   incrementally as you go.
1263
/// - Writing custom iterators over a rope's text data.
1264
///
1265
/// There are precisely two guarantees about the yielded chunks:
1266
///
1267
/// - All non-empty chunks are yielded, and they are yielded in order.
1268
/// - CRLF pairs are never split across chunks.
1269
///
1270
/// There are no guarantees about the size of yielded chunks, and except for
1271
/// CRLF pairs and being valid `str` slices there are no guarantees about
1272
/// where the chunks are split.  For example, they may be zero-sized, they
1273
/// don't necessarily align with line breaks, etc.
1274
#[derive(Debug, Clone)]
1275
pub struct Chunks<'a> {
1276
    iter: ChunksEnum<'a>,
1277
    is_reversed: bool,
1278
}
1279
1280
#[derive(Debug, Clone)]
1281
enum ChunksEnum<'a> {
1282
    Full {
1283
        node_stack: Vec<(&'a Arc<Node>, usize)>, // (node ref, index of current child)
1284
        total_bytes: usize,                      // Total bytes in the data range of the iterator.
1285
        byte_idx: isize, // The index of the current byte relative to the data range start.
1286
    },
1287
    Light {
1288
        text: &'a str,
1289
        is_end: bool,
1290
    },
1291
}
1292
1293
impl<'a> Chunks<'a> {
1294
    #[inline(always)]
1295
0
    pub(crate) fn new(node: &Arc<Node>) -> Chunks {
1296
0
        let info = node.text_info();
1297
0
        Chunks::new_with_range_at_byte(
1298
0
            node,
1299
0
            0,
1300
0
            (0, info.bytes as usize),
1301
0
            (0, info.chars as usize),
1302
0
            (0, info.line_breaks as usize + 1),
1303
0
        )
1304
0
        .0
1305
0
    }
1306
1307
    #[inline(always)]
1308
0
    pub(crate) fn new_with_range(
1309
0
        node: &Arc<Node>,
1310
0
        byte_idx_range: (usize, usize),
1311
0
        char_idx_range: (usize, usize),
1312
0
        line_break_idx_range: (usize, usize),
1313
0
    ) -> Chunks {
1314
0
        Chunks::new_with_range_at_byte(
1315
0
            node,
1316
0
            byte_idx_range.0,
1317
0
            byte_idx_range,
1318
0
            char_idx_range,
1319
0
            line_break_idx_range,
1320
0
        )
1321
0
        .0
1322
0
    }
1323
1324
    /// The main workhorse function for creating new `Chunks` iterators.
1325
    ///
1326
    /// Creates a new `Chunks` iterator from the given node, starting the
1327
    /// iterator at the chunk containing the `at_byte` byte index (i.e. the
1328
    /// `next()` method will yield the chunk containing that byte).  The range
1329
    /// of the iterator is bounded by `byte_idx_range`.
1330
    ///
1331
    /// Both `at_byte` and `byte_idx_range` are relative to the beginning of
1332
    /// of the passed node.
1333
    ///
1334
    /// Passing an `at_byte` equal to the max of `byte_idx_range` creates an
1335
    /// iterator at the end of forward iteration.
1336
    ///
1337
    /// Returns the iterator and the byte/char/line index of its start relative
1338
    /// to the start of the node.
1339
0
    pub(crate) fn new_with_range_at_byte(
1340
0
        node: &Arc<Node>,
1341
0
        at_byte: usize,
1342
0
        byte_idx_range: (usize, usize),
1343
0
        char_idx_range: (usize, usize),
1344
0
        line_break_idx_range: (usize, usize),
1345
0
    ) -> (Chunks, usize, usize, usize) {
1346
0
        debug_assert!(at_byte >= byte_idx_range.0);
1347
0
        debug_assert!(at_byte <= byte_idx_range.1);
1348
1349
        // For convenience/readability.
1350
0
        let start_byte = byte_idx_range.0;
1351
0
        let end_byte = byte_idx_range.1;
1352
1353
        // Special-case for empty text contents.
1354
0
        if start_byte == end_byte {
1355
0
            return (
1356
0
                Chunks {
1357
0
                    iter: ChunksEnum::Light {
1358
0
                        text: "",
1359
0
                        is_end: false,
1360
0
                    },
1361
0
                    is_reversed: false,
1362
0
                },
1363
0
                0,
1364
0
                0,
1365
0
                0,
1366
0
            );
1367
0
        }
1368
1369
        // If root is a leaf, return light version of the iter.
1370
0
        if node.is_leaf() {
1371
0
            let text = &node.leaf_text()[start_byte..end_byte];
1372
0
            if at_byte == end_byte {
1373
0
                return (
1374
0
                    Chunks {
1375
0
                        iter: ChunksEnum::Light {
1376
0
                            text: text,
1377
0
                            is_end: true,
1378
0
                        },
1379
0
                        is_reversed: false,
1380
0
                    },
1381
0
                    text.len(),
1382
0
                    count_chars(text),
1383
0
                    byte_to_line_idx(text, text.len()),
1384
0
                );
1385
            } else {
1386
0
                return (
1387
0
                    Chunks {
1388
0
                        iter: ChunksEnum::Light {
1389
0
                            text: text,
1390
0
                            is_end: false,
1391
0
                        },
1392
0
                        is_reversed: false,
1393
0
                    },
1394
0
                    0,
1395
0
                    0,
1396
0
                    0,
1397
0
                );
1398
            }
1399
0
        }
1400
1401
        // Create and populate the node stack, and determine the char index
1402
        // within the first chunk, and byte index of the start of that chunk.
1403
0
        let mut info = TextInfo::new();
1404
0
        let mut byte_idx = at_byte as isize;
1405
0
        let node_stack = {
1406
0
            let mut node_stack: Vec<(&Arc<Node>, usize)> = Vec::new();
1407
0
            let mut node_ref = node;
1408
            loop {
1409
0
                match **node_ref {
1410
0
                    Node::Leaf(ref text) => {
1411
0
                        if at_byte < end_byte || byte_idx == 0 {
1412
0
                            byte_idx = info.bytes as isize - start_byte as isize;
1413
0
                        } else {
1414
0
                            byte_idx =
1415
0
                                (info.bytes as isize + text.len() as isize) - start_byte as isize;
1416
0
                            info = TextInfo {
1417
0
                                bytes: byte_idx_range.1 as u64,
1418
0
                                chars: char_idx_range.1 as u64,
1419
0
                                utf16_surrogates: 0, // Bogus value, not needed
1420
0
                                line_breaks: line_break_idx_range.1 as u64 - 1,
1421
0
                            };
1422
0
                            (*node_stack.last_mut().unwrap()).1 += 1;
1423
0
                        }
1424
0
                        break;
1425
                    }
1426
0
                    Node::Internal(ref children) => {
1427
0
                        let (child_i, acc_info) = children.search_byte_idx(byte_idx as usize);
1428
0
                        info += acc_info;
1429
0
                        node_stack.push((node_ref, child_i));
1430
0
                        node_ref = &children.nodes()[child_i];
1431
0
                        byte_idx -= acc_info.bytes as isize;
1432
0
                    }
1433
                }
1434
            }
1435
0
            node_stack
1436
        };
1437
1438
        // Create the iterator.
1439
0
        (
1440
0
            Chunks {
1441
0
                iter: ChunksEnum::Full {
1442
0
                    node_stack: node_stack,
1443
0
                    total_bytes: end_byte - start_byte,
1444
0
                    byte_idx: byte_idx,
1445
0
                },
1446
0
                is_reversed: false,
1447
0
            },
1448
0
            (info.bytes as usize).max(byte_idx_range.0),
1449
0
            (info.chars as usize).max(char_idx_range.0),
1450
0
            (info.line_breaks as usize).max(line_break_idx_range.0),
1451
0
        )
1452
0
    }
1453
1454
    #[inline(always)]
1455
0
    pub(crate) fn new_with_range_at_char(
1456
0
        node: &Arc<Node>,
1457
0
        at_char: usize,
1458
0
        byte_idx_range: (usize, usize),
1459
0
        char_idx_range: (usize, usize),
1460
0
        line_break_idx_range: (usize, usize),
1461
0
    ) -> (Chunks, usize, usize, usize) {
1462
0
        let at_byte = if at_char == char_idx_range.1 {
1463
0
            byte_idx_range.1
1464
        } else {
1465
0
            (node.get_chunk_at_char(at_char).1.bytes as usize).max(byte_idx_range.0)
1466
        };
1467
1468
0
        Chunks::new_with_range_at_byte(
1469
0
            node,
1470
0
            at_byte,
1471
0
            byte_idx_range,
1472
0
            char_idx_range,
1473
0
            line_break_idx_range,
1474
        )
1475
0
    }
1476
1477
    #[inline(always)]
1478
0
    pub(crate) fn new_with_range_at_line_break(
1479
0
        node: &Arc<Node>,
1480
0
        at_line_break: usize,
1481
0
        byte_idx_range: (usize, usize),
1482
0
        char_idx_range: (usize, usize),
1483
0
        line_break_idx_range: (usize, usize),
1484
0
    ) -> (Chunks, usize, usize, usize) {
1485
0
        let at_byte = if at_line_break == line_break_idx_range.1 {
1486
0
            byte_idx_range.1
1487
        } else {
1488
0
            (node.get_chunk_at_line_break(at_line_break).1.bytes as usize).max(byte_idx_range.0)
1489
        };
1490
1491
0
        Chunks::new_with_range_at_byte(
1492
0
            node,
1493
0
            at_byte,
1494
0
            byte_idx_range,
1495
0
            char_idx_range,
1496
0
            line_break_idx_range,
1497
        )
1498
0
    }
1499
1500
0
    pub(crate) fn from_str(text: &str, at_end: bool) -> Chunks {
1501
0
        Chunks {
1502
0
            iter: ChunksEnum::Light {
1503
0
                text: text,
1504
0
                is_end: at_end,
1505
0
            },
1506
0
            is_reversed: false,
1507
0
        }
1508
0
    }
1509
1510
    /// Reverses the direction of the iterator in-place.
1511
    ///
1512
    /// In other words, swaps the behavior of [`prev()`](Chunks::prev())
1513
    /// and [`next()`](Chunks::next()).
1514
    #[inline]
1515
0
    pub fn reverse(&mut self) {
1516
0
        self.is_reversed = !self.is_reversed;
1517
0
    }
1518
1519
    /// Same as `reverse()`, but returns itself.
1520
    ///
1521
    /// This is useful when chaining iterator methods:
1522
    ///
1523
    /// ```rust
1524
    /// # use ropey::Rope;
1525
    /// # let rope = Rope::from_str("Hello there\n world!\n");
1526
    /// // Enumerate the rope's chunks in reverse, starting from the end.
1527
    /// for (i, chunk) in rope.chunks_at_byte(rope.len_bytes()).0.reversed().enumerate() {
1528
    ///     println!("{} {}", i, chunk);
1529
    /// #   assert_eq!(chunk, rope.chunks().nth(rope.chunks().count() - i - 1).unwrap());
1530
    /// }
1531
    #[inline]
1532
    #[must_use]
1533
0
    pub fn reversed(mut self) -> Chunks<'a> {
1534
0
        self.reverse();
1535
0
        self
1536
0
    }
1537
1538
    /// Advances the iterator backwards and returns the previous value.
1539
    ///
1540
    /// Runs in amortized O(1) time and worst-case O(log N) time.
1541
    #[inline(always)]
1542
0
    pub fn prev(&mut self) -> Option<&'a str> {
1543
0
        if !self.is_reversed {
1544
0
            self.prev_impl()
1545
        } else {
1546
0
            self.next_impl()
1547
        }
1548
0
    }
1549
1550
0
    fn prev_impl(&mut self) -> Option<&'a str> {
1551
0
        match *self {
1552
            Chunks {
1553
                iter:
1554
                    ChunksEnum::Full {
1555
0
                        ref mut node_stack,
1556
0
                        total_bytes,
1557
0
                        ref mut byte_idx,
1558
                    },
1559
                ..
1560
            } => {
1561
0
                if *byte_idx <= 0 {
1562
0
                    return None;
1563
0
                }
1564
1565
                // Progress the node stack if needed.
1566
0
                let mut stack_idx = node_stack.len() - 1;
1567
0
                if node_stack[stack_idx].1 == 0 {
1568
0
                    while node_stack[stack_idx].1 == 0 {
1569
0
                        if stack_idx == 0 {
1570
0
                            return None;
1571
0
                        } else {
1572
0
                            stack_idx -= 1;
1573
0
                        }
1574
                    }
1575
0
                    node_stack[stack_idx].1 -= 1;
1576
0
                    while stack_idx < (node_stack.len() - 1) {
1577
0
                        let child_i = node_stack[stack_idx].1;
1578
0
                        let node = &node_stack[stack_idx].0.children().nodes()[child_i];
1579
0
                        node_stack[stack_idx + 1] = (node, node.child_count() - 1);
1580
0
                        stack_idx += 1;
1581
0
                    }
1582
0
                    node_stack[stack_idx].1 += 1;
1583
0
                }
1584
1585
                // Fetch the node and child index.
1586
0
                let (node, ref mut child_i) = node_stack.last_mut().unwrap();
1587
0
                *child_i -= 1;
1588
1589
                // Get the text, sliced to the appropriate range.
1590
0
                let text = node.children().nodes()[*child_i].leaf_text();
1591
0
                *byte_idx -= text.len() as isize;
1592
0
                let text_slice = {
1593
0
                    let start_byte = if *byte_idx < 0 {
1594
0
                        (-*byte_idx) as usize
1595
                    } else {
1596
0
                        0
1597
                    };
1598
0
                    let end_byte = text.len().min((total_bytes as isize - *byte_idx) as usize);
1599
0
                    &text[start_byte..end_byte]
1600
                };
1601
1602
                // Return the text.
1603
0
                return Some(text_slice);
1604
            }
1605
1606
            Chunks {
1607
                iter:
1608
                    ChunksEnum::Light {
1609
0
                        text,
1610
0
                        ref mut is_end,
1611
                    },
1612
                ..
1613
            } => {
1614
0
                if !*is_end || text.is_empty() {
1615
0
                    return None;
1616
                } else {
1617
0
                    *is_end = false;
1618
0
                    return Some(text);
1619
                }
1620
            }
1621
        }
1622
0
    }
1623
1624
0
    fn next_impl(&mut self) -> Option<&'a str> {
1625
0
        match *self {
1626
            Chunks {
1627
                iter:
1628
                    ChunksEnum::Full {
1629
0
                        ref mut node_stack,
1630
0
                        total_bytes,
1631
0
                        ref mut byte_idx,
1632
                    },
1633
                ..
1634
            } => {
1635
0
                if *byte_idx >= total_bytes as isize {
1636
0
                    return None;
1637
0
                }
1638
1639
                // Progress the node stack if needed.
1640
0
                let mut stack_idx = node_stack.len() - 1;
1641
0
                if node_stack[stack_idx].1 >= node_stack[stack_idx].0.child_count() {
1642
0
                    while node_stack[stack_idx].1 >= (node_stack[stack_idx].0.child_count() - 1) {
1643
0
                        if stack_idx == 0 {
1644
0
                            return None;
1645
0
                        } else {
1646
0
                            stack_idx -= 1;
1647
0
                        }
1648
                    }
1649
0
                    node_stack[stack_idx].1 += 1;
1650
0
                    while stack_idx < (node_stack.len() - 1) {
1651
0
                        let child_i = node_stack[stack_idx].1;
1652
0
                        let node = &node_stack[stack_idx].0.children().nodes()[child_i];
1653
0
                        node_stack[stack_idx + 1] = (node, 0);
1654
0
                        stack_idx += 1;
1655
0
                    }
1656
0
                }
1657
1658
                // Fetch the node and child index.
1659
0
                let (node, ref mut child_i) = node_stack.last_mut().unwrap();
1660
1661
                // Get the text, sliced to the appropriate range.
1662
0
                let text = node.children().nodes()[*child_i].leaf_text();
1663
0
                let text_slice = {
1664
0
                    let start_byte = if *byte_idx < 0 {
1665
0
                        (-*byte_idx) as usize
1666
                    } else {
1667
0
                        0
1668
                    };
1669
0
                    let end_byte = text.len().min((total_bytes as isize - *byte_idx) as usize);
1670
0
                    &text[start_byte..end_byte]
1671
                };
1672
1673
                // Book keeping.
1674
0
                *byte_idx += text.len() as isize;
1675
0
                *child_i += 1;
1676
1677
                // Return the text.
1678
0
                return Some(text_slice);
1679
            }
1680
1681
            Chunks {
1682
                iter:
1683
                    ChunksEnum::Light {
1684
0
                        text,
1685
0
                        ref mut is_end,
1686
                    },
1687
                ..
1688
            } => {
1689
0
                if *is_end || text.is_empty() {
1690
0
                    return None;
1691
                } else {
1692
0
                    *is_end = true;
1693
0
                    return Some(text);
1694
                }
1695
            }
1696
        }
1697
0
    }
1698
}
1699
1700
impl<'a> Iterator for Chunks<'a> {
1701
    type Item = &'a str;
1702
1703
    /// Advances the iterator forward and returns the next value.
1704
    ///
1705
    /// Runs in amortized O(1) time and worst-case O(log N) time.
1706
    #[inline(always)]
1707
0
    fn next(&mut self) -> Option<&'a str> {
1708
0
        if !self.is_reversed {
1709
0
            self.next_impl()
1710
        } else {
1711
0
            self.prev_impl()
1712
        }
1713
0
    }
1714
}
1715
1716
#[cfg(test)]
1717
mod tests {
1718
    #![allow(clippy::while_let_on_iterator)]
1719
    use super::*;
1720
    use crate::Rope;
1721
1722
    const TEXT: &str = "\r\n\
1723
                        Hello there!  How're you doing?  It's a fine day, \
1724
                        isn't it?  Aren't you glad we're alive?\r\n\
1725
                        こんにちは!元気ですか?日はいいですね。\
1726
                        私たちが生きだって嬉しいではないか?\r\n\
1727
                        Hello there!  How're you doing?  It's a fine day, \
1728
                        isn't it?  Aren't you glad we're alive?\r\n\
1729
                        こんにちは!元気ですか?日はいいですね。\
1730
                        私たちが生きだって嬉しいではないか?\r\n\
1731
                        Hello there!  How're you doing?  It's a fine day, \
1732
                        isn't it?  Aren't you glad we're alive?\r\n\
1733
                        こんにちは!元気ですか?日はいいですね。\
1734
                        私たちが生きだって嬉しいではないか?\r\n\
1735
                        Hello there!  How're you doing?  It's a fine day, \
1736
                        isn't it?  Aren't you glad we're alive?\r\n\
1737
                        こんにちは!元気ですか?日はいいですね。\
1738
                        私たちが生きだって嬉しいではないか?\r\n\
1739
                        Hello there!  How're you doing?  It's a fine day, \
1740
                        isn't it?  Aren't you glad we're alive?\r\n\
1741
                        こんにちは!元気ですか?日はいいですね。\
1742
                        私たちが生きだって嬉しいではないか?\r\n\
1743
                        Hello there!  How're you doing?  It's a fine day, \
1744
                        isn't it?  Aren't you glad we're alive?\r\n\
1745
                        こんにちは!元気ですか?日はいいですね。\
1746
                        私たちが生きだって嬉しいではないか?\r\n\
1747
                        Hello there!  How're you doing?  It's a fine day, \
1748
                        isn't it?  Aren't you glad we're alive?\r\n\
1749
                        こんにちは!元気ですか?日はいいですね。\
1750
                        私たちが生きだって嬉しいではないか?\r\n\
1751
                        Hello there!  How're you doing?  It's a fine day, \
1752
                        isn't it?  Aren't you glad we're alive?\r\n\
1753
                        こんにちは!元気ですか?日はいいですね。\
1754
                        私たちが生きだって嬉しいではないか?\r\n\
1755
                        Hello there!  How're you doing?  It's a fine day, \
1756
                        isn't it?  Aren't you glad we're alive?\r\n\
1757
                        こんにちは!元気ですか?日はいいですね。\
1758
                        私たちが生きだって嬉しいではないか?\r\n\
1759
                        Hello there!  How're you doing?  It's a fine day, \
1760
                        isn't it?  Aren't you glad we're alive?\r\n\
1761
                        こんにちは!元気ですか?日はいいですね。\
1762
                        私たちが生きだって嬉しいではないか?\r\n\
1763
                        Hello there!  How're you doing?  It's a fine day, \
1764
                        isn't it?  Aren't you glad we're alive?\r\n\
1765
                        こんにちは!元気ですか?日はいいですね。\
1766
                        私たちが生きだって嬉しいではないか?\r\n\
1767
                        Hello there!  How're you doing?  It's a fine day, \
1768
                        isn't it?  Aren't you glad we're alive?\r\n\
1769
                        こんにちは!元気ですか?日はいいですね。\
1770
                        私たちが生きだって嬉しいではないか?\r\n\
1771
                        Hello there!  How're you doing?  It's a fine day, \
1772
                        isn't it?  Aren't you glad we're alive?\r\n\
1773
                        こんにちは!元気ですか?日はいいですね。\
1774
                        私たちが生きだって嬉しいではないか?\r\n\
1775
                        Hello there!  How're you doing?  It's a fine day, \
1776
                        isn't it?  Aren't you glad we're alive?\r\n\
1777
                        こんにちは!元気ですか?日はいいですね。\
1778
                        私たちが生きだって嬉しいではないか?\r\n\
1779
                        Hello there!  How're you doing?  It's a fine day, \
1780
                        isn't it?  Aren't you glad we're alive?\r\n\
1781
                        こんにちは!元気ですか?日はいいですね。\
1782
                        私たちが生きだって嬉しいではないか?\r\n\
1783
                        Hello there!  How're you doing?  It's a fine day, \
1784
                        isn't it?  Aren't you glad we're alive?\r\n\
1785
                        こんにちは!元気ですか?日はいいですね。\
1786
                        私たちが生きだって嬉しいではないか?\r\n\
1787
                        ";
1788
1789
    #[test]
1790
    #[cfg_attr(miri, ignore)]
1791
    fn bytes_01() {
1792
        let r = Rope::from_str(TEXT);
1793
        for (br, bt) in r.bytes().zip(TEXT.bytes()) {
1794
            assert_eq!(br, bt);
1795
        }
1796
    }
1797
1798
    #[test]
1799
    #[cfg_attr(miri, ignore)]
1800
    fn bytes_02() {
1801
        let r = Rope::from_str(TEXT);
1802
        let mut itr = r.bytes();
1803
        while let Some(_) = itr.next() {}
1804
1805
        let mut i = TEXT.len();
1806
        while let Some(b) = itr.prev() {
1807
            i -= 1;
1808
            assert_eq!(b, TEXT.as_bytes()[i]);
1809
        }
1810
    }
1811
1812
    #[test]
1813
    #[cfg_attr(miri, ignore)]
1814
    fn bytes_03() {
1815
        let r = Rope::from_str(TEXT);
1816
        let mut itr = r.bytes();
1817
1818
        itr.next();
1819
        itr.prev();
1820
        assert_eq!(None, itr.prev());
1821
    }
1822
1823
    #[test]
1824
    #[cfg_attr(miri, ignore)]
1825
    fn bytes_04() {
1826
        let r = Rope::from_str(TEXT);
1827
        let mut itr = r.bytes();
1828
        while let Some(_) = itr.next() {}
1829
1830
        itr.prev();
1831
        itr.next();
1832
        assert_eq!(None, itr.next());
1833
    }
1834
1835
    #[test]
1836
    #[cfg_attr(miri, ignore)]
1837
    fn bytes_05() {
1838
        let r = Rope::from_str(TEXT);
1839
        let mut itr = r.bytes();
1840
1841
        assert_eq!(None, itr.prev());
1842
        itr.next();
1843
        itr.prev();
1844
        assert_eq!(None, itr.prev());
1845
    }
1846
1847
    #[test]
1848
    #[cfg_attr(miri, ignore)]
1849
    fn bytes_06() {
1850
        let r = Rope::from_str(TEXT);
1851
        let mut itr = r.bytes();
1852
        while let Some(_) = itr.next() {}
1853
1854
        assert_eq!(None, itr.next());
1855
        itr.prev();
1856
        itr.next();
1857
        assert_eq!(None, itr.next());
1858
    }
1859
1860
    #[test]
1861
    #[cfg_attr(miri, ignore)]
1862
    fn bytes_07() {
1863
        let mut itr = Bytes::from_str("a");
1864
1865
        assert_eq!(Some(0x61), itr.next());
1866
        assert_eq!(None, itr.next());
1867
        assert_eq!(Some(0x61), itr.prev());
1868
        assert_eq!(None, itr.prev());
1869
    }
1870
1871
    #[test]
1872
    #[cfg_attr(miri, ignore)]
1873
    fn bytes_at_01() {
1874
        let r = Rope::from_str(TEXT);
1875
1876
        let mut bytes_1 = TEXT.bytes();
1877
        for i in 0..(r.len_bytes() + 1) {
1878
            let mut bytes_2 = r.bytes_at(i);
1879
            assert_eq!(bytes_1.next(), bytes_2.next());
1880
        }
1881
    }
1882
1883
    #[test]
1884
    #[cfg_attr(miri, ignore)]
1885
    fn bytes_at_02() {
1886
        let r = Rope::from_str(TEXT);
1887
        let mut bytes = r.bytes_at(r.len_bytes());
1888
        assert_eq!(bytes.next(), None);
1889
    }
1890
1891
    #[test]
1892
    #[cfg_attr(miri, ignore)]
1893
    fn bytes_at_03() {
1894
        let r = Rope::from_str(TEXT);
1895
        let mut bytes_1 = r.bytes_at(r.len_bytes());
1896
        let mut bytes_2 = TEXT.bytes();
1897
1898
        while let Some(b) = bytes_2.next_back() {
1899
            assert_eq!(bytes_1.prev(), Some(b));
1900
        }
1901
    }
1902
1903
    #[test]
1904
    #[cfg_attr(miri, ignore)]
1905
    fn bytes_exact_size_iter_01() {
1906
        let r = Rope::from_str(TEXT);
1907
        let s = r.slice(34..301);
1908
1909
        let mut byte_count = s.len_bytes();
1910
        let mut bytes = s.bytes();
1911
1912
        assert_eq!(byte_count, bytes.len());
1913
1914
        while let Some(_) = bytes.next() {
1915
            byte_count -= 1;
1916
            assert_eq!(byte_count, bytes.len());
1917
        }
1918
1919
        bytes.next();
1920
        bytes.next();
1921
        bytes.next();
1922
        bytes.next();
1923
        bytes.next();
1924
        bytes.next();
1925
        bytes.next();
1926
        assert_eq!(bytes.len(), 0);
1927
        assert_eq!(byte_count, 0);
1928
    }
1929
1930
    #[test]
1931
    #[cfg_attr(miri, ignore)]
1932
    fn bytes_exact_size_iter_02() {
1933
        let r = Rope::from_str(TEXT);
1934
        let s = r.slice(34..301);
1935
1936
        for i in 0..=s.len_bytes() {
1937
            let bytes = s.bytes_at(i);
1938
            assert_eq!(s.len_bytes() - i, bytes.len());
1939
        }
1940
    }
1941
1942
    #[test]
1943
    #[cfg_attr(miri, ignore)]
1944
    fn bytes_exact_size_iter_03() {
1945
        let r = Rope::from_str(TEXT);
1946
        let s = r.slice(34..301);
1947
1948
        let mut byte_count = 0;
1949
        let mut bytes = s.bytes_at(s.len_bytes());
1950
1951
        assert_eq!(byte_count, bytes.len());
1952
1953
        while bytes.prev().is_some() {
1954
            byte_count += 1;
1955
            assert_eq!(byte_count, bytes.len());
1956
        }
1957
1958
        assert_eq!(bytes.len(), s.len_bytes());
1959
        bytes.prev();
1960
        bytes.prev();
1961
        bytes.prev();
1962
        bytes.prev();
1963
        bytes.prev();
1964
        bytes.prev();
1965
        bytes.prev();
1966
        assert_eq!(bytes.len(), s.len_bytes());
1967
        assert_eq!(byte_count, s.len_bytes());
1968
    }
1969
1970
    #[test]
1971
    #[cfg_attr(miri, ignore)]
1972
    fn bytes_reverse_01() {
1973
        let r = Rope::from_str(TEXT);
1974
        let mut itr = r.bytes();
1975
        let mut stack = Vec::new();
1976
1977
        for _ in 0..32 {
1978
            stack.push(itr.next().unwrap());
1979
        }
1980
        itr.reverse();
1981
        for _ in 0..32 {
1982
            assert_eq!(stack.pop(), itr.next());
1983
        }
1984
    }
1985
1986
    #[test]
1987
    #[cfg_attr(miri, ignore)]
1988
    fn bytes_reverse_02() {
1989
        let r = Rope::from_str(TEXT);
1990
        let mut itr = r.bytes_at(r.len_bytes() / 3);
1991
        let mut stack = Vec::new();
1992
1993
        for _ in 0..32 {
1994
            stack.push(itr.next().unwrap());
1995
        }
1996
        itr.reverse();
1997
        for _ in 0..32 {
1998
            assert_eq!(stack.pop(), itr.next());
1999
        }
2000
    }
2001
2002
    #[test]
2003
    #[cfg_attr(miri, ignore)]
2004
    fn bytes_reverse_03() {
2005
        let r = Rope::from_str(TEXT);
2006
        let mut itr = r.bytes_at(r.len_bytes() / 3);
2007
        let mut stack = Vec::new();
2008
2009
        itr.reverse();
2010
        for _ in 0..32 {
2011
            stack.push(itr.next().unwrap());
2012
        }
2013
        itr.reverse();
2014
        for _ in 0..32 {
2015
            assert_eq!(stack.pop(), itr.next());
2016
        }
2017
    }
2018
2019
    #[test]
2020
    #[cfg_attr(miri, ignore)]
2021
    fn bytes_reverse_04() {
2022
        let mut itr = Bytes::from_str("a");
2023
2024
        assert_eq!(Some(0x61), itr.next());
2025
        assert_eq!(None, itr.next());
2026
        itr.reverse();
2027
        assert_eq!(Some(0x61), itr.next());
2028
        assert_eq!(None, itr.next());
2029
    }
2030
2031
    #[test]
2032
    #[cfg_attr(miri, ignore)]
2033
    fn bytes_reverse_exact_size_iter_01() {
2034
        let r = Rope::from_str(TEXT);
2035
        let s = r.slice(34..301);
2036
2037
        let mut bytes = s.bytes_at(42);
2038
        bytes.reverse();
2039
        let mut byte_count = 42;
2040
2041
        assert_eq!(42, bytes.len());
2042
2043
        while let Some(_) = bytes.next() {
2044
            byte_count -= 1;
2045
            assert_eq!(byte_count, bytes.len());
2046
        }
2047
2048
        bytes.next();
2049
        bytes.next();
2050
        bytes.next();
2051
        bytes.next();
2052
        bytes.next();
2053
        bytes.next();
2054
        bytes.next();
2055
        assert_eq!(bytes.len(), 0);
2056
        assert_eq!(byte_count, 0);
2057
    }
2058
2059
    #[test]
2060
    #[cfg_attr(miri, ignore)]
2061
    fn chars_01() {
2062
        let r = Rope::from_str(TEXT);
2063
        for (cr, ct) in r.chars().zip(TEXT.chars()) {
2064
            assert_eq!(cr, ct);
2065
        }
2066
    }
2067
2068
    #[test]
2069
    #[cfg_attr(miri, ignore)]
2070
    fn chars_02() {
2071
        let r = Rope::from_str(TEXT);
2072
        let mut itr = r.chars();
2073
        let mut text_itr = TEXT.chars();
2074
        while let Some(_) = itr.next() {}
2075
2076
        while let Some(b) = itr.prev() {
2077
            assert_eq!(b, text_itr.next_back().unwrap());
2078
        }
2079
    }
2080
2081
    #[test]
2082
    #[cfg_attr(miri, ignore)]
2083
    fn chars_03() {
2084
        let r = Rope::from_str(TEXT);
2085
        let mut itr = r.chars();
2086
2087
        itr.next();
2088
        itr.prev();
2089
        assert_eq!(None, itr.prev());
2090
    }
2091
2092
    #[test]
2093
    #[cfg_attr(miri, ignore)]
2094
    fn chars_04() {
2095
        let r = Rope::from_str(TEXT);
2096
        let mut itr = r.chars();
2097
        while let Some(_) = itr.next() {}
2098
2099
        itr.prev();
2100
        itr.next();
2101
        assert_eq!(None, itr.next());
2102
    }
2103
2104
    #[test]
2105
    #[cfg_attr(miri, ignore)]
2106
    fn chars_05() {
2107
        let r = Rope::from_str(TEXT);
2108
        let mut itr = r.chars();
2109
2110
        assert_eq!(None, itr.prev());
2111
        itr.next();
2112
        itr.prev();
2113
        assert_eq!(None, itr.prev());
2114
    }
2115
2116
    #[test]
2117
    #[cfg_attr(miri, ignore)]
2118
    fn chars_06() {
2119
        let r = Rope::from_str(TEXT);
2120
        let mut itr = r.chars();
2121
        while let Some(_) = itr.next() {}
2122
2123
        assert_eq!(None, itr.next());
2124
        itr.prev();
2125
        itr.next();
2126
        assert_eq!(None, itr.next());
2127
    }
2128
2129
    #[test]
2130
    #[cfg_attr(miri, ignore)]
2131
    fn chars_07() {
2132
        let mut itr = Chars::from_str("a");
2133
2134
        assert_eq!(Some('a'), itr.next());
2135
        assert_eq!(None, itr.next());
2136
        assert_eq!(Some('a'), itr.prev());
2137
        assert_eq!(None, itr.prev());
2138
    }
2139
2140
    #[test]
2141
    #[cfg_attr(miri, ignore)]
2142
    fn chars_at_01() {
2143
        let r = Rope::from_str(TEXT);
2144
2145
        let mut chars_1 = TEXT.chars();
2146
        for i in 0..(r.len_chars() + 1) {
2147
            let mut chars_2 = r.chars_at(i);
2148
            assert_eq!(chars_1.next(), chars_2.next());
2149
        }
2150
    }
2151
2152
    #[test]
2153
    #[cfg_attr(miri, ignore)]
2154
    fn chars_at_02() {
2155
        let r = Rope::from_str(TEXT);
2156
        let mut chars = r.chars_at(r.len_chars());
2157
        assert_eq!(chars.next(), None);
2158
    }
2159
2160
    #[test]
2161
    #[cfg_attr(miri, ignore)]
2162
    fn chars_at_03() {
2163
        let r = Rope::from_str(TEXT);
2164
        let mut chars_1 = r.chars_at(r.len_chars());
2165
        let mut chars_2 = TEXT.chars();
2166
2167
        while let Some(c) = chars_2.next_back() {
2168
            assert_eq!(chars_1.prev(), Some(c));
2169
        }
2170
    }
2171
2172
    #[test]
2173
    #[cfg_attr(miri, ignore)]
2174
    fn chars_exact_size_iter_01() {
2175
        let r = Rope::from_str(TEXT);
2176
        let s = r.slice(34..301);
2177
2178
        let mut char_count = s.len_chars();
2179
        let mut chars = s.chars();
2180
2181
        assert_eq!(char_count, chars.len());
2182
2183
        while let Some(_) = chars.next() {
2184
            char_count -= 1;
2185
            assert_eq!(char_count, chars.len());
2186
        }
2187
2188
        assert_eq!(char_count, 0);
2189
        assert_eq!(chars.len(), 0);
2190
    }
2191
2192
    #[test]
2193
    #[cfg_attr(miri, ignore)]
2194
    fn chars_exact_size_iter_02() {
2195
        let r = Rope::from_str(TEXT);
2196
        let s = r.slice(34..301);
2197
2198
        for i in 0..=s.len_chars() {
2199
            let chars = s.chars_at(i);
2200
            assert_eq!(s.len_chars() - i, chars.len());
2201
        }
2202
    }
2203
2204
    #[test]
2205
    #[cfg_attr(miri, ignore)]
2206
    fn chars_exact_size_iter_03() {
2207
        let r = Rope::from_str(TEXT);
2208
        let s = r.slice(34..301);
2209
2210
        let mut char_count = 0;
2211
        let mut chars = s.chars_at(s.len_chars());
2212
2213
        assert_eq!(char_count, chars.len());
2214
2215
        while chars.prev().is_some() {
2216
            char_count += 1;
2217
            assert_eq!(char_count, chars.len());
2218
        }
2219
2220
        assert_eq!(char_count, s.len_chars());
2221
        assert_eq!(chars.len(), s.len_chars());
2222
        chars.prev();
2223
        assert_eq!(chars.len(), s.len_chars());
2224
    }
2225
2226
    #[test]
2227
    #[cfg_attr(miri, ignore)]
2228
    fn chars_reverse_01() {
2229
        let r = Rope::from_str(TEXT);
2230
        let mut itr = r.chars();
2231
        let mut stack = Vec::new();
2232
2233
        for _ in 0..32 {
2234
            stack.push(itr.next().unwrap());
2235
        }
2236
        itr.reverse();
2237
        for _ in 0..32 {
2238
            assert_eq!(stack.pop(), itr.next());
2239
        }
2240
    }
2241
2242
    #[test]
2243
    #[cfg_attr(miri, ignore)]
2244
    fn chars_reverse_02() {
2245
        let r = Rope::from_str(TEXT);
2246
        let mut itr = r.chars_at(r.len_chars() / 3);
2247
        let mut stack = Vec::new();
2248
2249
        for _ in 0..32 {
2250
            stack.push(itr.next().unwrap());
2251
        }
2252
        itr.reverse();
2253
        for _ in 0..32 {
2254
            assert_eq!(stack.pop(), itr.next());
2255
        }
2256
    }
2257
2258
    #[test]
2259
    #[cfg_attr(miri, ignore)]
2260
    fn chars_reverse_03() {
2261
        let r = Rope::from_str(TEXT);
2262
        let mut itr = r.chars_at(r.len_chars() / 3);
2263
        let mut stack = Vec::new();
2264
2265
        itr.reverse();
2266
        for _ in 0..32 {
2267
            stack.push(itr.next().unwrap());
2268
        }
2269
        itr.reverse();
2270
        for _ in 0..32 {
2271
            assert_eq!(stack.pop(), itr.next());
2272
        }
2273
    }
2274
2275
    #[test]
2276
    #[cfg_attr(miri, ignore)]
2277
    fn chars_reverse_04() {
2278
        let mut itr = Chars::from_str("a");
2279
2280
        assert_eq!(Some('a'), itr.next());
2281
        assert_eq!(None, itr.next());
2282
        itr.reverse();
2283
        assert_eq!(Some('a'), itr.next());
2284
        assert_eq!(None, itr.next());
2285
    }
2286
2287
    #[test]
2288
    #[cfg_attr(miri, ignore)]
2289
    fn chars_reverse_exact_size_iter_01() {
2290
        let r = Rope::from_str(TEXT);
2291
        let s = r.slice(34..301);
2292
2293
        let mut chars = s.chars_at(42);
2294
        chars.reverse();
2295
        let mut char_count = 42;
2296
2297
        assert_eq!(42, chars.len());
2298
2299
        while let Some(_) = chars.next() {
2300
            char_count -= 1;
2301
            assert_eq!(char_count, chars.len());
2302
        }
2303
2304
        chars.next();
2305
        chars.next();
2306
        chars.next();
2307
        chars.next();
2308
        chars.next();
2309
        chars.next();
2310
        chars.next();
2311
        assert_eq!(chars.len(), 0);
2312
        assert_eq!(char_count, 0);
2313
    }
2314
2315
    #[test]
2316
    #[cfg_attr(miri, ignore)]
2317
    fn lines_21() {
2318
        let r = Rope::from_str("a\nb\nc\nd\ne\nf\ng\nh\n");
2319
        for (line, c) in r.lines().zip('a'..='h') {
2320
            assert_eq!(line, format!("{c}\n"))
2321
        }
2322
        for (line, c) in r
2323
            .lines_at(r.len_lines() - 1)
2324
            .reversed()
2325
            .zip(('a'..='h').rev())
2326
        {
2327
            assert_eq!(line, format!("{c}\n"))
2328
        }
2329
2330
        let r = Rope::from_str("ab\nc\nd\ne\nf\ng\nh\n");
2331
        for (line, c) in r.slice(1..).lines().zip('b'..='h') {
2332
            assert_eq!(line, format!("{c}\n"))
2333
        }
2334
    }
2335
2336
    #[test]
2337
    #[cfg_attr(miri, ignore)]
2338
    fn lines_01() {
2339
        let r = Rope::from_str(TEXT);
2340
        let s = r.slice(..);
2341
2342
        assert_eq!(34, r.lines().count());
2343
        assert_eq!(34, s.lines().count());
2344
2345
        // Rope
2346
        let mut lines = r.lines();
2347
        assert_eq!("\r\n", lines.next().unwrap());
2348
        for _ in 0..16 {
2349
            assert_eq!(
2350
                "Hello there!  How're you doing?  It's a fine day, \
2351
                 isn't it?  Aren't you glad we're alive?\r\n",
2352
                lines.next().unwrap()
2353
            );
2354
            assert_eq!(
2355
                "こんにちは!元気ですか?日はいいですね。\
2356
                 私たちが生きだって嬉しいではないか?\r\n",
2357
                lines.next().unwrap()
2358
            );
2359
        }
2360
        assert_eq!("", lines.next().unwrap());
2361
        assert!(lines.next().is_none());
2362
2363
        // Slice
2364
        let mut lines = s.lines();
2365
        assert_eq!("\r\n", lines.next().unwrap());
2366
        for _ in 0..16 {
2367
            assert_eq!(
2368
                "Hello there!  How're you doing?  It's a fine day, \
2369
                 isn't it?  Aren't you glad we're alive?\r\n",
2370
                lines.next().unwrap()
2371
            );
2372
            assert_eq!(
2373
                "こんにちは!元気ですか?日はいいですね。\
2374
                 私たちが生きだって嬉しいではないか?\r\n",
2375
                lines.next().unwrap()
2376
            );
2377
        }
2378
        assert_eq!("", lines.next().unwrap());
2379
        assert!(lines.next().is_none());
2380
    }
2381
2382
    #[test]
2383
    #[cfg_attr(miri, ignore)]
2384
    fn lines_02() {
2385
        let text = "Hello there!\nHow goes it?";
2386
        let r = Rope::from_str(text);
2387
        let s = r.slice(..);
2388
2389
        assert_eq!(2, r.lines().count());
2390
        assert_eq!(2, s.lines().count());
2391
2392
        let mut lines = r.lines();
2393
        assert_eq!("Hello there!\n", lines.next().unwrap());
2394
        assert_eq!("How goes it?", lines.next().unwrap());
2395
        assert!(lines.next().is_none());
2396
2397
        let mut lines = s.lines();
2398
        assert_eq!("Hello there!\n", lines.next().unwrap());
2399
        assert_eq!("How goes it?", lines.next().unwrap());
2400
        assert!(lines.next().is_none());
2401
    }
2402
2403
    #[test]
2404
    #[cfg_attr(miri, ignore)]
2405
    fn lines_03() {
2406
        let text = "Hello there!\nHow goes it?\n";
2407
        let r = Rope::from_str(text);
2408
        let s = r.slice(..);
2409
2410
        assert_eq!(3, r.lines().count());
2411
        assert_eq!(3, s.lines().count());
2412
2413
        let mut lines = r.lines();
2414
        assert_eq!("Hello there!\n", lines.next().unwrap());
2415
        assert_eq!("How goes it?\n", lines.next().unwrap());
2416
        assert_eq!("", lines.next().unwrap());
2417
        assert!(lines.next().is_none());
2418
2419
        let mut lines = s.lines();
2420
        assert_eq!("Hello there!\n", lines.next().unwrap());
2421
        assert_eq!("How goes it?\n", lines.next().unwrap());
2422
        assert_eq!("", lines.next().unwrap());
2423
        assert!(lines.next().is_none());
2424
    }
2425
2426
    #[test]
2427
    #[cfg_attr(miri, ignore)]
2428
    fn lines_04() {
2429
        let text = "Hello there!\nHow goes it?\nYeah!";
2430
        let r = Rope::from_str(text);
2431
        let s1 = r.slice(..25);
2432
        let s2 = r.slice(..26);
2433
2434
        assert_eq!(2, s1.lines().count());
2435
        assert_eq!(3, s2.lines().count());
2436
2437
        let mut lines = s1.lines();
2438
        assert_eq!("Hello there!\n", lines.next().unwrap());
2439
        assert_eq!("How goes it?", lines.next().unwrap());
2440
        assert!(lines.next().is_none());
2441
2442
        let mut lines = s2.lines();
2443
        assert_eq!("Hello there!\n", lines.next().unwrap());
2444
        assert_eq!("How goes it?\n", lines.next().unwrap());
2445
        assert_eq!("", lines.next().unwrap());
2446
        assert!(lines.next().is_none());
2447
    }
2448
2449
    #[test]
2450
    #[cfg_attr(miri, ignore)]
2451
    fn lines_05() {
2452
        let text = "";
2453
        let r = Rope::from_str(text);
2454
        let s = r.slice(..);
2455
2456
        assert_eq!(1, r.lines().count());
2457
        assert_eq!(1, s.lines().count());
2458
2459
        let mut lines = r.lines();
2460
        assert_eq!("", lines.next().unwrap());
2461
        assert!(lines.next().is_none());
2462
2463
        let mut lines = s.lines();
2464
        assert_eq!("", lines.next().unwrap());
2465
        assert!(lines.next().is_none());
2466
    }
2467
2468
    #[test]
2469
    #[cfg_attr(miri, ignore)]
2470
    fn lines_06() {
2471
        let text = "a";
2472
        let r = Rope::from_str(text);
2473
        let s = r.slice(..);
2474
2475
        assert_eq!(1, r.lines().count());
2476
        assert_eq!(1, s.lines().count());
2477
2478
        let mut lines = r.lines();
2479
        assert_eq!("a", lines.next().unwrap());
2480
        assert!(lines.next().is_none());
2481
2482
        let mut lines = s.lines();
2483
        assert_eq!("a", lines.next().unwrap());
2484
        assert!(lines.next().is_none());
2485
    }
2486
2487
    #[test]
2488
    #[cfg_attr(miri, ignore)]
2489
    fn lines_07() {
2490
        let text = "a\nb";
2491
        let r = Rope::from_str(text);
2492
        let s = r.slice(..);
2493
2494
        assert_eq!(2, r.lines().count());
2495
        assert_eq!(2, s.lines().count());
2496
2497
        let mut lines = r.lines();
2498
        assert_eq!("a\n", lines.next().unwrap());
2499
        assert_eq!("b", lines.next().unwrap());
2500
        assert!(lines.next().is_none());
2501
2502
        let mut lines = s.lines();
2503
        assert_eq!("a\n", lines.next().unwrap());
2504
        assert_eq!("b", lines.next().unwrap());
2505
        assert!(lines.next().is_none());
2506
    }
2507
2508
    #[test]
2509
    #[cfg_attr(miri, ignore)]
2510
    fn lines_08() {
2511
        let text = "\n";
2512
        let r = Rope::from_str(text);
2513
        let s = r.slice(..);
2514
2515
        assert_eq!(2, r.lines().count());
2516
        assert_eq!(2, s.lines().count());
2517
2518
        let mut lines = r.lines();
2519
        assert_eq!("\n", lines.next().unwrap());
2520
        assert_eq!("", lines.next().unwrap());
2521
        assert!(lines.next().is_none());
2522
2523
        let mut lines = s.lines();
2524
        assert_eq!("\n", lines.next().unwrap());
2525
        assert_eq!("", lines.next().unwrap());
2526
        assert!(lines.next().is_none());
2527
    }
2528
2529
    #[test]
2530
    #[cfg_attr(miri, ignore)]
2531
    fn lines_09() {
2532
        let text = "a\nb\n";
2533
        let r = Rope::from_str(text);
2534
        let s = r.slice(..);
2535
2536
        assert_eq!(3, r.lines().count());
2537
        assert_eq!(3, s.lines().count());
2538
2539
        let mut lines = r.lines();
2540
        assert_eq!("a\n", lines.next().unwrap());
2541
        assert_eq!("b\n", lines.next().unwrap());
2542
        assert_eq!("", lines.next().unwrap());
2543
        assert!(lines.next().is_none());
2544
2545
        let mut lines = s.lines();
2546
        assert_eq!("a\n", lines.next().unwrap());
2547
        assert_eq!("b\n", lines.next().unwrap());
2548
        assert_eq!("", lines.next().unwrap());
2549
        assert!(lines.next().is_none());
2550
    }
2551
2552
    #[test]
2553
    #[cfg_attr(miri, ignore)]
2554
    fn lines_10() {
2555
        let r = Rope::from_str(TEXT);
2556
2557
        let mut itr = r.lines();
2558
2559
        assert_eq!(None, itr.prev());
2560
        assert_eq!(None, itr.prev());
2561
    }
2562
2563
    #[test]
2564
    #[cfg_attr(miri, ignore)]
2565
    fn lines_11() {
2566
        let r = Rope::from_str(TEXT);
2567
2568
        let mut lines = Vec::new();
2569
        let mut itr = r.lines();
2570
2571
        while let Some(line) = itr.next() {
2572
            lines.push(line);
2573
        }
2574
2575
        while let Some(line) = itr.prev() {
2576
            assert_eq!(line, lines.pop().unwrap());
2577
        }
2578
2579
        assert!(lines.is_empty());
2580
    }
2581
2582
    #[test]
2583
    #[cfg_attr(miri, ignore)]
2584
    fn lines_12() {
2585
        let r = Rope::from_str(TEXT);
2586
        let s = r.slice(34..301);
2587
2588
        let mut lines = Vec::new();
2589
        let mut itr = s.lines();
2590
2591
        while let Some(line) = itr.next() {
2592
            lines.push(line);
2593
        }
2594
2595
        while let Some(line) = itr.prev() {
2596
            assert_eq!(line, lines.pop().unwrap());
2597
        }
2598
2599
        assert!(lines.is_empty());
2600
    }
2601
2602
    #[test]
2603
    #[cfg_attr(miri, ignore)]
2604
    fn lines_13() {
2605
        let text = "";
2606
        let r = Rope::from_str(text);
2607
        let s = r.slice(..);
2608
2609
        let mut lines = Vec::new();
2610
        let mut itr = s.lines();
2611
2612
        while let Some(text) = itr.next() {
2613
            lines.push(text);
2614
        }
2615
2616
        while let Some(text) = itr.prev() {
2617
            assert_eq!(text, lines.pop().unwrap());
2618
        }
2619
2620
        assert!(lines.is_empty());
2621
    }
2622
2623
    #[test]
2624
    #[cfg_attr(miri, ignore)]
2625
    fn lines_14() {
2626
        let text = "a";
2627
        let r = Rope::from_str(text);
2628
        let s = r.slice(..);
2629
2630
        let mut lines = Vec::new();
2631
        let mut itr = s.lines();
2632
2633
        while let Some(text) = itr.next() {
2634
            lines.push(text);
2635
        }
2636
2637
        while let Some(text) = itr.prev() {
2638
            assert_eq!(text, lines.pop().unwrap());
2639
        }
2640
2641
        assert!(lines.is_empty());
2642
    }
2643
2644
    #[test]
2645
    #[cfg_attr(miri, ignore)]
2646
    fn lines_15() {
2647
        let text = "a\nb";
2648
        let r = Rope::from_str(text);
2649
        let s = r.slice(..);
2650
2651
        let mut lines = Vec::new();
2652
        let mut itr = s.lines();
2653
2654
        while let Some(text) = itr.next() {
2655
            lines.push(text);
2656
        }
2657
2658
        while let Some(text) = itr.prev() {
2659
            assert_eq!(text, lines.pop().unwrap());
2660
        }
2661
2662
        assert!(lines.is_empty());
2663
    }
2664
2665
    #[test]
2666
    #[cfg_attr(miri, ignore)]
2667
    fn lines_16() {
2668
        let text = "\n";
2669
        let r = Rope::from_str(text);
2670
        let s = r.slice(..);
2671
2672
        let mut lines = Vec::new();
2673
        let mut itr = s.lines();
2674
2675
        while let Some(text) = itr.next() {
2676
            lines.push(text);
2677
        }
2678
2679
        while let Some(text) = itr.prev() {
2680
            assert_eq!(text, lines.pop().unwrap());
2681
        }
2682
2683
        assert!(lines.is_empty());
2684
    }
2685
2686
    #[test]
2687
    #[cfg_attr(miri, ignore)]
2688
    fn lines_17() {
2689
        let text = "a\nb\n";
2690
        let r = Rope::from_str(text);
2691
        let s = r.slice(..);
2692
2693
        let mut lines = Vec::new();
2694
        let mut itr = s.lines();
2695
2696
        while let Some(text) = itr.next() {
2697
            lines.push(text);
2698
        }
2699
2700
        while let Some(text) = itr.prev() {
2701
            assert_eq!(text, lines.pop().unwrap());
2702
        }
2703
2704
        assert!(lines.is_empty());
2705
    }
2706
2707
    #[test]
2708
    #[cfg_attr(miri, ignore)]
2709
    fn lines_at_01() {
2710
        let r = Rope::from_str(TEXT);
2711
2712
        for i in 0..r.len_lines() {
2713
            let line = r.line(i);
2714
            let mut lines = r.lines_at(i);
2715
            assert_eq!(Some(line), lines.next());
2716
        }
2717
2718
        let mut lines = r.lines_at(r.len_lines());
2719
        assert_eq!(None, lines.next());
2720
    }
2721
2722
    #[test]
2723
    #[cfg_attr(miri, ignore)]
2724
    fn lines_at_02() {
2725
        let r = Rope::from_str(TEXT);
2726
        let s = r.slice(34..301);
2727
2728
        for i in 0..s.len_lines() {
2729
            let line = s.line(i);
2730
            let mut lines = s.lines_at(i);
2731
            assert_eq!(Some(line), lines.next());
2732
        }
2733
2734
        let mut lines = s.lines_at(s.len_lines());
2735
        assert_eq!(None, lines.next());
2736
    }
2737
2738
    #[test]
2739
    #[cfg_attr(miri, ignore)]
2740
    fn lines_at_03() {
2741
        let r = Rope::from_str(TEXT);
2742
        let s = r.slice(34..34);
2743
2744
        let mut lines = s.lines_at(0);
2745
        assert_eq!("", lines.next().unwrap());
2746
2747
        let mut lines = s.lines_at(1);
2748
        assert_eq!(None, lines.next());
2749
    }
2750
2751
    #[test]
2752
    #[cfg_attr(miri, ignore)]
2753
    fn lines_exact_size_iter_01() {
2754
        let r = Rope::from_str(TEXT);
2755
        let s = r.slice(34..301);
2756
2757
        let mut line_count = s.len_lines();
2758
        let mut lines = s.lines();
2759
2760
        assert_eq!(line_count, lines.len());
2761
2762
        while let Some(_) = lines.next() {
2763
            line_count -= 1;
2764
            assert_eq!(line_count, lines.len());
2765
        }
2766
2767
        assert_eq!(lines.len(), 0);
2768
        lines.next();
2769
        lines.next();
2770
        lines.next();
2771
        lines.next();
2772
        lines.next();
2773
        lines.next();
2774
        lines.next();
2775
        assert_eq!(lines.len(), 0);
2776
        assert_eq!(line_count, 0);
2777
    }
2778
2779
    #[test]
2780
    #[cfg_attr(miri, ignore)]
2781
    fn lines_exact_size_iter_02() {
2782
        let r = Rope::from_str(TEXT);
2783
        let s = r.slice(34..301);
2784
2785
        for i in 0..=s.len_lines() {
2786
            let lines = s.lines_at(i);
2787
            assert_eq!(s.len_lines() - i, lines.len());
2788
        }
2789
    }
2790
2791
    #[test]
2792
    #[cfg_attr(miri, ignore)]
2793
    fn lines_exact_size_iter_03() {
2794
        let r = Rope::from_str(TEXT);
2795
        let s = r.slice(34..301);
2796
2797
        let mut line_count = 0;
2798
        let mut lines = s.lines_at(s.len_lines());
2799
2800
        assert_eq!(line_count, lines.len());
2801
2802
        while lines.prev().is_some() {
2803
            line_count += 1;
2804
            assert_eq!(line_count, lines.len());
2805
        }
2806
2807
        assert_eq!(lines.len(), s.len_lines());
2808
        lines.prev();
2809
        lines.prev();
2810
        lines.prev();
2811
        lines.prev();
2812
        lines.prev();
2813
        lines.prev();
2814
        lines.prev();
2815
        assert_eq!(lines.len(), s.len_lines());
2816
        assert_eq!(line_count, s.len_lines());
2817
    }
2818
2819
    #[test]
2820
    #[cfg_attr(miri, ignore)]
2821
    fn lines_exact_size_iter_04() {
2822
        // Make sure splitting CRLF pairs at the end works properly.
2823
        let r = Rope::from_str("\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n");
2824
        for i in 0..r.len_chars() {
2825
            let s = r.slice(..i);
2826
            let lines = s.lines();
2827
            if cfg!(any(feature = "cr_lines", feature = "unicode_lines")) {
2828
                assert_eq!(lines.len(), 1 + ((i + 1) / 2));
2829
            } else {
2830
                assert_eq!(lines.len(), 1 + (i / 2));
2831
            }
2832
            assert_eq!(lines.len(), lines.count());
2833
        }
2834
    }
2835
2836
    #[test]
2837
    #[cfg_attr(miri, ignore)]
2838
    fn lines_reverse_01() {
2839
        let r = Rope::from_str(TEXT);
2840
        let mut itr = r.lines();
2841
        let mut stack = Vec::new();
2842
2843
        for _ in 0..8 {
2844
            stack.push(itr.next().unwrap());
2845
        }
2846
        itr.reverse();
2847
        for _ in 0..8 {
2848
            assert_eq!(stack.pop().unwrap(), itr.next().unwrap());
2849
        }
2850
    }
2851
2852
    #[test]
2853
    #[cfg_attr(miri, ignore)]
2854
    fn lines_reverse_02() {
2855
        let r = Rope::from_str(TEXT);
2856
        let mut itr = r.lines_at(r.len_lines() / 3);
2857
        let mut stack = Vec::new();
2858
2859
        for _ in 0..8 {
2860
            stack.push(itr.next().unwrap());
2861
        }
2862
        itr.reverse();
2863
        for _ in 0..8 {
2864
            assert_eq!(stack.pop().unwrap(), itr.next().unwrap());
2865
        }
2866
    }
2867
2868
    #[test]
2869
    #[cfg_attr(miri, ignore)]
2870
    fn lines_reverse_03() {
2871
        let r = Rope::from_str(TEXT);
2872
        let mut itr = r.lines_at(r.len_lines() / 3);
2873
        let mut stack = Vec::new();
2874
2875
        itr.reverse();
2876
        for _ in 0..8 {
2877
            stack.push(itr.next().unwrap());
2878
        }
2879
        itr.reverse();
2880
        for _ in 0..8 {
2881
            assert_eq!(stack.pop().unwrap(), itr.next().unwrap());
2882
        }
2883
    }
2884
2885
    #[test]
2886
    #[cfg_attr(miri, ignore)]
2887
    fn lines_reverse_04() {
2888
        let mut itr = Lines::from_str("a\n", 1);
2889
2890
        assert_eq!(Some("a\n".into()), itr.next());
2891
        assert_eq!(Some("".into()), itr.next());
2892
        assert_eq!(None, itr.next());
2893
        itr.reverse();
2894
        assert_eq!(Some("".into()), itr.next());
2895
        assert_eq!(Some("a\n".into()), itr.next());
2896
        assert_eq!(None, itr.next());
2897
    }
2898
2899
    #[test]
2900
    #[cfg_attr(miri, ignore)]
2901
    fn lines_reverse_exact_size_iter_01() {
2902
        let r = Rope::from_str(TEXT);
2903
        let s = r.slice(34..301);
2904
2905
        let mut lines = s.lines_at(4);
2906
        lines.reverse();
2907
        let mut line_count = 4;
2908
2909
        assert_eq!(4, lines.len());
2910
2911
        while let Some(_) = lines.next() {
2912
            line_count -= 1;
2913
            assert_eq!(line_count, lines.len());
2914
        }
2915
2916
        lines.next();
2917
        lines.next();
2918
        lines.next();
2919
        lines.next();
2920
        lines.next();
2921
        lines.next();
2922
        lines.next();
2923
        assert_eq!(lines.len(), 0);
2924
        assert_eq!(line_count, 0);
2925
    }
2926
2927
    #[test]
2928
    #[cfg_attr(miri, ignore)]
2929
    fn lines_reverse_exact_size_iter_02() {
2930
        // Make sure splitting CRLF pairs at the end works properly.
2931
        let r = Rope::from_str("\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n");
2932
        for i in 0..r.len_chars() {
2933
            let s = r.slice(..i);
2934
            let lines = s.lines_at((i + 1) / 2).reversed();
2935
            assert_eq!(lines.len(), lines.count());
2936
        }
2937
    }
2938
2939
    #[test]
2940
    #[cfg_attr(miri, ignore)]
2941
    fn chunks_01() {
2942
        let r = Rope::from_str(TEXT);
2943
2944
        let mut idx = 0;
2945
        for chunk in r.chunks() {
2946
            assert_eq!(chunk, &TEXT[idx..(idx + chunk.len())]);
2947
            idx += chunk.len();
2948
        }
2949
    }
2950
2951
    #[test]
2952
    #[cfg_attr(miri, ignore)]
2953
    fn chunks_02() {
2954
        let r = Rope::from_str("");
2955
        let mut itr = r.chunks();
2956
2957
        assert_eq!(None, itr.next());
2958
    }
2959
2960
    #[test]
2961
    #[cfg_attr(miri, ignore)]
2962
    fn chunks_03() {
2963
        let r = Rope::from_str(TEXT);
2964
2965
        let mut itr = r.chunks();
2966
2967
        assert_eq!(None, itr.prev());
2968
    }
2969
2970
    #[test]
2971
    #[cfg_attr(miri, ignore)]
2972
    fn chunks_04() {
2973
        let r = Rope::from_str(TEXT);
2974
2975
        let mut chunks = Vec::new();
2976
        let mut itr = r.chunks();
2977
2978
        while let Some(text) = itr.next() {
2979
            chunks.push(text);
2980
        }
2981
2982
        while let Some(text) = itr.prev() {
2983
            assert_eq!(text, chunks.pop().unwrap());
2984
        }
2985
2986
        assert!(chunks.is_empty());
2987
    }
2988
2989
    #[test]
2990
    #[cfg_attr(miri, ignore)]
2991
    fn chunks_at_byte_01() {
2992
        let r = Rope::from_str(TEXT);
2993
2994
        for i in 0..r.len_bytes() {
2995
            let (chunk, b, c, l) = r.chunk_at_byte(i);
2996
            let (mut chunks, bs, cs, ls) = r.chunks_at_byte(i);
2997
2998
            assert_eq!(b, bs);
2999
            assert_eq!(c, cs);
3000
            assert_eq!(l, ls);
3001
            assert_eq!(Some(chunk), chunks.next());
3002
        }
3003
    }
3004
3005
    #[test]
3006
    #[cfg_attr(miri, ignore)]
3007
    fn chunks_at_byte_02() {
3008
        let r = Rope::from_str(TEXT);
3009
        let s = r.slice(34..301);
3010
3011
        for i in 0..(s.len_chars() + 1) {
3012
            let (chunk, b, c, l) = s.chunk_at_byte(i);
3013
            let (mut chunks, bs, cs, ls) = s.chunks_at_byte(i);
3014
3015
            assert_eq!(b, bs);
3016
            assert_eq!(c, cs);
3017
            assert_eq!(l, ls);
3018
            assert_eq!(Some(chunk), chunks.next());
3019
        }
3020
    }
3021
3022
    #[test]
3023
    #[cfg_attr(miri, ignore)]
3024
    fn chunks_at_byte_03() {
3025
        let r = Rope::from_str(TEXT);
3026
        let s = r.slice(34..301);
3027
3028
        let (mut chunks, _, _, _) = s.chunks_at_byte(s.len_bytes());
3029
        assert_eq!(chunks.next(), None);
3030
3031
        let (mut chunks, _, _, _) = s.chunks_at_byte(s.len_bytes());
3032
        assert_eq!(s.chunks().last(), chunks.prev());
3033
    }
3034
3035
    #[test]
3036
    #[cfg_attr(miri, ignore)]
3037
    fn chunks_at_byte_04() {
3038
        let r = Rope::from_str(TEXT);
3039
        let s = r.slice(34..34);
3040
3041
        let (mut chunks, _, _, _) = s.chunks_at_byte(0);
3042
        assert_eq!(chunks.next(), None);
3043
3044
        let (mut chunks, _, _, _) = s.chunks_at_byte(0);
3045
        assert_eq!(chunks.prev(), None);
3046
    }
3047
3048
    #[test]
3049
    #[cfg_attr(miri, ignore)]
3050
    fn chunks_at_char_01() {
3051
        let r = Rope::from_str(TEXT);
3052
3053
        for i in 0..r.len_chars() {
3054
            let (chunk, b, c, l) = r.chunk_at_char(i);
3055
            let (mut chunks, bs, cs, ls) = r.chunks_at_char(i);
3056
3057
            assert_eq!(b, bs);
3058
            assert_eq!(c, cs);
3059
            assert_eq!(l, ls);
3060
            assert_eq!(Some(chunk), chunks.next());
3061
        }
3062
    }
3063
3064
    #[test]
3065
    #[cfg_attr(miri, ignore)]
3066
    fn chunks_at_char_02() {
3067
        let r = Rope::from_str(TEXT);
3068
        let s = r.slice(34..301);
3069
3070
        for i in 0..s.len_chars() {
3071
            let (chunk, b, c, l) = s.chunk_at_char(i);
3072
            let (mut chunks, bs, cs, ls) = s.chunks_at_char(i);
3073
3074
            assert_eq!(b, bs);
3075
            assert_eq!(c, cs);
3076
            assert_eq!(l, ls);
3077
            assert_eq!(Some(chunk), chunks.next());
3078
        }
3079
    }
3080
3081
    #[test]
3082
    #[cfg_attr(miri, ignore)]
3083
    fn chunks_at_char_03() {
3084
        let r = Rope::from_str(TEXT);
3085
        let s = r.slice(34..301);
3086
3087
        let (mut chunks, _, _, _) = s.chunks_at_char(s.len_chars());
3088
        assert_eq!(chunks.next(), None);
3089
    }
3090
3091
    #[test]
3092
    #[cfg_attr(miri, ignore)]
3093
    fn chunks_at_char_04() {
3094
        let r = Rope::from_str(TEXT);
3095
        let s = r.slice(34..34);
3096
3097
        let (mut chunks, _, _, _) = s.chunks_at_char(0);
3098
        assert_eq!(chunks.next(), None);
3099
3100
        let (mut chunks, _, _, _) = s.chunks_at_char(0);
3101
        assert_eq!(chunks.prev(), None);
3102
    }
3103
3104
    #[test]
3105
    #[cfg_attr(miri, ignore)]
3106
    fn chunks_at_line_break_01() {
3107
        let r = Rope::from_str(TEXT);
3108
3109
        for i in 0..r.len_lines() {
3110
            let (chunk, b, c, l) = r.chunk_at_line_break(i);
3111
            let (mut chunks, bs, cs, ls) = r.chunks_at_line_break(i);
3112
3113
            assert_eq!(b, bs);
3114
            assert_eq!(c, cs);
3115
            assert_eq!(l, ls);
3116
            assert_eq!(Some(chunk), chunks.next());
3117
        }
3118
    }
3119
3120
    #[test]
3121
    #[cfg_attr(miri, ignore)]
3122
    fn chunks_at_line_break_02() {
3123
        let r = Rope::from_str(TEXT);
3124
        let s = r.slice(34..301);
3125
3126
        for i in 0..s.len_lines() {
3127
            let (chunk, b, c, l) = s.chunk_at_line_break(i);
3128
            let (mut chunks, bs, cs, ls) = s.chunks_at_line_break(i);
3129
3130
            assert_eq!(Some(chunk), chunks.next());
3131
            assert_eq!(b, bs);
3132
            assert_eq!(c, cs);
3133
            assert_eq!(l, ls);
3134
        }
3135
    }
3136
3137
    #[test]
3138
    #[cfg_attr(miri, ignore)]
3139
    fn chunks_at_line_break_03() {
3140
        let r = Rope::from_str(TEXT);
3141
        let s = r.slice(34..301);
3142
3143
        let (mut chunks, _, _, _) = s.chunks_at_line_break(s.len_lines());
3144
        assert_eq!(chunks.next(), None);
3145
    }
3146
3147
    #[test]
3148
    #[cfg_attr(miri, ignore)]
3149
    fn chunks_at_line_break_04() {
3150
        let r = Rope::from_str(TEXT);
3151
        let s = r.slice(34..34);
3152
3153
        let (mut chunks, _, _, _) = s.chunks_at_line_break(0);
3154
        assert_eq!(chunks.next(), None);
3155
3156
        let (mut chunks, _, _, _) = s.chunks_at_line_break(0);
3157
        assert_eq!(chunks.prev(), None);
3158
    }
3159
3160
    #[test]
3161
    #[cfg_attr(miri, ignore)]
3162
    fn chunks_reverse_01() {
3163
        let r = Rope::from_str(TEXT);
3164
        let mut itr = r.chunks();
3165
        let mut stack = Vec::new();
3166
3167
        for _ in 0..8 {
3168
            stack.push(itr.next().unwrap());
3169
        }
3170
        itr.reverse();
3171
        for _ in 0..8 {
3172
            assert_eq!(stack.pop().unwrap(), itr.next().unwrap());
3173
        }
3174
    }
3175
3176
    #[test]
3177
    #[cfg_attr(miri, ignore)]
3178
    fn chunks_reverse_02() {
3179
        let r = Rope::from_str(TEXT);
3180
        let mut itr = r.chunks_at_char(r.len_chars() / 3).0;
3181
        let mut stack = Vec::new();
3182
3183
        for _ in 0..8 {
3184
            stack.push(itr.next().unwrap());
3185
        }
3186
        itr.reverse();
3187
        for _ in 0..8 {
3188
            assert_eq!(stack.pop().unwrap(), itr.next().unwrap());
3189
        }
3190
    }
3191
3192
    #[test]
3193
    #[cfg_attr(miri, ignore)]
3194
    fn chunks_reverse_03() {
3195
        let r = Rope::from_str(TEXT);
3196
        let mut itr = r.chunks_at_char(r.len_chars() / 3).0;
3197
        let mut stack = Vec::new();
3198
3199
        itr.reverse();
3200
        for _ in 0..8 {
3201
            stack.push(itr.next().unwrap());
3202
        }
3203
        itr.reverse();
3204
        for _ in 0..8 {
3205
            assert_eq!(stack.pop().unwrap(), itr.next().unwrap());
3206
        }
3207
    }
3208
3209
    #[test]
3210
    #[cfg_attr(miri, ignore)]
3211
    fn chunks_reverse_04() {
3212
        let mut itr = Chunks::from_str("a\n", false);
3213
3214
        assert_eq!(Some("a\n"), itr.next());
3215
        assert_eq!(None, itr.next());
3216
        itr.reverse();
3217
        assert_eq!(Some("a\n"), itr.next());
3218
        assert_eq!(None, itr.next());
3219
    }
3220
3221
    #[test]
3222
    #[cfg_attr(miri, ignore)]
3223
    fn bytes_sliced_01() {
3224
        let r = Rope::from_str(TEXT);
3225
3226
        let s_start = 34;
3227
        let s_end = 301;
3228
        let s_start_byte = r.char_to_byte(s_start);
3229
        let s_end_byte = r.char_to_byte(s_end);
3230
3231
        let s1 = r.slice(s_start..s_end);
3232
        let s2 = &TEXT[s_start_byte..s_end_byte];
3233
3234
        let mut s1_bytes = s1.bytes();
3235
        let mut s2_bytes = s2.bytes();
3236
3237
        assert_eq!(s1, s2);
3238
        assert_eq!(s1.byte(0), s2.as_bytes()[0]);
3239
3240
        assert_eq!(s1.len_bytes(), s2.len());
3241
        assert_eq!(s1_bytes.len(), s2.len());
3242
3243
        for _ in 0..(s2.len() + 1) {
3244
            assert_eq!(s1_bytes.next(), s2_bytes.next());
3245
        }
3246
3247
        assert_eq!(s1_bytes.len(), 0);
3248
    }
3249
3250
    #[test]
3251
    #[cfg_attr(miri, ignore)]
3252
    fn bytes_sliced_reverse_01() {
3253
        let r = Rope::from_str(TEXT);
3254
3255
        let s_start = 34;
3256
        let s_end = 301;
3257
        let s = r.slice(s_start..s_end);
3258
3259
        let mut itr = s.bytes();
3260
        let mut stack = Vec::new();
3261
        for _ in 0..32 {
3262
            stack.push(itr.next().unwrap());
3263
        }
3264
        itr.reverse();
3265
        for _ in 0..32 {
3266
            assert_eq!(stack.pop(), itr.next());
3267
        }
3268
    }
3269
3270
    #[test]
3271
    #[cfg_attr(miri, ignore)]
3272
    fn bytes_at_sliced_01() {
3273
        let r = Rope::from_str(TEXT);
3274
3275
        let s_start = 34;
3276
        let s_end = 301;
3277
        let s_start_byte = r.char_to_byte(s_start);
3278
        let s_end_byte = r.char_to_byte(s_end);
3279
3280
        let s1 = r.slice(s_start..s_end);
3281
        let s2 = &TEXT[s_start_byte..s_end_byte];
3282
3283
        let mut bytes_1 = s2.bytes();
3284
        for i in 0..(s1.len_bytes() + 1) {
3285
            let mut bytes_2 = s1.bytes_at(i);
3286
            assert_eq!(bytes_1.next(), bytes_2.next());
3287
        }
3288
    }
3289
3290
    #[test]
3291
    #[cfg_attr(miri, ignore)]
3292
    fn bytes_at_sliced_02() {
3293
        let r = Rope::from_str(TEXT);
3294
        let s = r.slice(34..301);
3295
        let mut bytes = s.bytes_at(s.len_bytes());
3296
        assert_eq!(bytes.next(), None);
3297
    }
3298
3299
    #[test]
3300
    #[cfg_attr(miri, ignore)]
3301
    fn bytes_at_sliced_03() {
3302
        let r = Rope::from_str(TEXT);
3303
3304
        let s_start = 34;
3305
        let s_end = 301;
3306
        let s_start_byte = r.char_to_byte(s_start);
3307
        let s_end_byte = r.char_to_byte(s_end);
3308
3309
        let s1 = r.slice(s_start..s_end);
3310
        let s2 = &TEXT[s_start_byte..s_end_byte];
3311
3312
        let mut bytes_1 = s1.bytes_at(s1.len_bytes());
3313
        let mut bytes_2 = s2.bytes();
3314
        while let Some(b) = bytes_2.next_back() {
3315
            assert_eq!(bytes_1.prev(), Some(b));
3316
        }
3317
    }
3318
3319
    #[test]
3320
    #[cfg_attr(miri, ignore)]
3321
    fn bytes_at_sliced_reverse_01() {
3322
        let r = Rope::from_str(TEXT);
3323
3324
        let s_start = 34;
3325
        let s_end = 301;
3326
        let s = r.slice(s_start..s_end);
3327
3328
        let mut itr = s.bytes_at(s.len_bytes() / 3);
3329
        let mut stack = Vec::new();
3330
        for _ in 0..32 {
3331
            stack.push(itr.next().unwrap());
3332
        }
3333
        itr.reverse();
3334
        for _ in 0..32 {
3335
            assert_eq!(stack.pop(), itr.next());
3336
        }
3337
    }
3338
3339
    #[test]
3340
    #[cfg_attr(miri, ignore)]
3341
    fn chars_sliced_01() {
3342
        let r = Rope::from_str(TEXT);
3343
3344
        let s_start = 34;
3345
        let s_end = 301;
3346
        let s_start_byte = r.char_to_byte(s_start);
3347
        let s_end_byte = r.char_to_byte(s_end);
3348
3349
        let s1 = r.slice(s_start..s_end);
3350
        let s2 = &TEXT[s_start_byte..s_end_byte];
3351
3352
        for (cr, ct) in s1.chars().zip(s2.chars()) {
3353
            assert_eq!(cr, ct);
3354
        }
3355
    }
3356
3357
    #[test]
3358
    #[cfg_attr(miri, ignore)]
3359
    fn chars_sliced_reverse_01() {
3360
        let r = Rope::from_str(TEXT);
3361
3362
        let s_start = 34;
3363
        let s_end = 301;
3364
        let s = r.slice(s_start..s_end);
3365
3366
        let mut itr = s.chars();
3367
        let mut stack = Vec::new();
3368
        for _ in 0..32 {
3369
            stack.push(itr.next().unwrap());
3370
        }
3371
        itr.reverse();
3372
        for _ in 0..32 {
3373
            assert_eq!(stack.pop(), itr.next());
3374
        }
3375
    }
3376
3377
    #[test]
3378
    #[cfg_attr(miri, ignore)]
3379
    fn chars_at_sliced_01() {
3380
        let r = Rope::from_str(TEXT);
3381
3382
        let s_start = 34;
3383
        let s_end = 301;
3384
        let s_start_byte = r.char_to_byte(s_start);
3385
        let s_end_byte = r.char_to_byte(s_end);
3386
3387
        let s1 = r.slice(s_start..s_end);
3388
        let s2 = &TEXT[s_start_byte..s_end_byte];
3389
3390
        let mut chars_1 = s2.chars();
3391
        for i in 0..(s1.len_chars() + 1) {
3392
            let mut chars_2 = s1.chars_at(i);
3393
            assert_eq!(chars_1.next(), chars_2.next());
3394
        }
3395
    }
3396
3397
    #[test]
3398
    #[cfg_attr(miri, ignore)]
3399
    fn chars_at_sliced_02() {
3400
        let r = Rope::from_str(TEXT);
3401
        let s = r.slice(34..301);
3402
        let mut chars = s.chars_at(s.len_chars());
3403
        assert_eq!(chars.next(), None);
3404
    }
3405
3406
    #[test]
3407
    #[cfg_attr(miri, ignore)]
3408
    fn chars_at_sliced_03() {
3409
        let r = Rope::from_str(TEXT);
3410
3411
        let s_start = 34;
3412
        let s_end = 301;
3413
        let s_start_char = r.char_to_byte(s_start);
3414
        let s_end_char = r.char_to_byte(s_end);
3415
3416
        let s1 = r.slice(s_start..s_end);
3417
        let s2 = &TEXT[s_start_char..s_end_char];
3418
3419
        let mut chars_1 = s1.chars_at(s1.len_chars());
3420
        let mut chars_2 = s2.chars();
3421
        while let Some(c) = chars_2.next_back() {
3422
            assert_eq!(chars_1.prev(), Some(c));
3423
        }
3424
    }
3425
3426
    #[test]
3427
    #[cfg_attr(miri, ignore)]
3428
    fn chars_at_sliced_reverse_01() {
3429
        let r = Rope::from_str(TEXT);
3430
3431
        let s_start = 34;
3432
        let s_end = 301;
3433
        let s = r.slice(s_start..s_end);
3434
3435
        let mut itr = s.chars_at(s.len_chars() / 3);
3436
        let mut stack = Vec::new();
3437
        for _ in 0..32 {
3438
            stack.push(itr.next().unwrap());
3439
        }
3440
        itr.reverse();
3441
        for _ in 0..32 {
3442
            assert_eq!(stack.pop(), itr.next());
3443
        }
3444
    }
3445
3446
    #[test]
3447
    #[cfg_attr(miri, ignore)]
3448
    fn lines_sliced_01() {
3449
        let r = Rope::from_str(TEXT);
3450
3451
        let s_start = 34;
3452
        let s_end = 301;
3453
        let s_start_byte = r.char_to_byte(s_start);
3454
        let s_end_byte = r.char_to_byte(s_end);
3455
3456
        let s1 = r.slice(s_start..s_end);
3457
        let s2 = &TEXT[s_start_byte..s_end_byte];
3458
3459
        for (liner, linet) in s1.lines().zip(s2.lines()) {
3460
            assert_eq!(liner.to_string().trim_end(), linet);
3461
        }
3462
    }
3463
3464
    #[test]
3465
    #[cfg_attr(miri, ignore)]
3466
    fn lines_sliced_reverse_01() {
3467
        let r = Rope::from_str(TEXT);
3468
3469
        let s_start = 34;
3470
        let s_end = 301;
3471
        let s = r.slice(s_start..s_end);
3472
3473
        let mut itr = s.lines();
3474
        let mut stack = Vec::new();
3475
        for _ in 0..4 {
3476
            stack.push(itr.next().unwrap());
3477
        }
3478
        itr.reverse();
3479
        for _ in 0..4 {
3480
            assert_eq!(stack.pop().unwrap(), itr.next().unwrap());
3481
        }
3482
    }
3483
3484
    #[test]
3485
    #[cfg_attr(miri, ignore)]
3486
    fn chunks_sliced_01() {
3487
        let r = Rope::from_str(TEXT);
3488
3489
        let s_start = 34;
3490
        let s_end = 301;
3491
        let s_start_byte = r.char_to_byte(s_start);
3492
        let s_end_byte = r.char_to_byte(s_end);
3493
3494
        let s1 = r.slice(s_start..s_end);
3495
        let s2 = &TEXT[s_start_byte..s_end_byte];
3496
3497
        let mut idx = 0;
3498
        for chunk in s1.chunks() {
3499
            assert_eq!(chunk, &s2[idx..(idx + chunk.len())]);
3500
            idx += chunk.len();
3501
        }
3502
3503
        assert_eq!(idx, s2.len());
3504
    }
3505
3506
    #[test]
3507
    #[cfg_attr(miri, ignore)]
3508
    fn chunks_sliced_reverse_01() {
3509
        let r = Rope::from_str(TEXT);
3510
3511
        let s_start = 34;
3512
        let s_end = 301;
3513
        let s = r.slice(s_start..s_end);
3514
3515
        let mut itr = s.chunks();
3516
        let mut stack = Vec::new();
3517
        for _ in 0..8 {
3518
            stack.push(itr.next().unwrap());
3519
        }
3520
        itr.reverse();
3521
        for _ in 0..8 {
3522
            assert_eq!(stack.pop(), itr.next());
3523
        }
3524
    }
3525
3526
    #[test]
3527
    #[cfg_attr(miri, ignore)]
3528
    fn empty_iter() {
3529
        let rope = Rope::from_str("");
3530
        let r: Vec<_> = rope.lines().collect();
3531
        assert_eq!(&[""], &*r)
3532
    }
3533
}