Skip to main content

xi_rope/
rope.rs

1// Copyright 2016 The xi-editor Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! A rope data structure with a line count metric and (soon) other useful
16//! info.
17
18use std::borrow::Cow;
19use std::cmp::{max, min};
20use std::fmt;
21use std::ops::Add;
22use std::str::{self, FromStr};
23use std::string::ParseError;
24
25use crate::delta::{Delta, DeltaElement};
26use crate::interval::{Interval, IntervalBounds};
27use crate::tree::{Cursor, DefaultMetric, Leaf, Metric, Node, NodeInfo, TreeBuilder};
28
29use bytecount;
30use memchr::{memchr, memrchr};
31
32use unicode_segmentation::GraphemeCursor;
33use unicode_segmentation::GraphemeIncomplete;
34
35const MIN_LEAF: usize = 511;
36const MAX_LEAF: usize = 1024;
37
38/// A rope data structure.
39///
40/// A [rope](https://en.wikipedia.org/wiki/Rope_(data_structure)) is a data structure
41/// for strings, specialized for incremental editing operations. Most operations
42/// (such as insert, delete, substring) are O(log n). This module provides an immutable
43/// (also known as [persistent](https://en.wikipedia.org/wiki/Persistent_data_structure))
44/// version of Ropes, and if there are many copies of similar strings, the common parts
45/// are shared.
46///
47/// Internally, the implementation uses thread safe reference counting.
48/// Mutations are generally copy-on-write, though in-place edits are
49/// supported as an optimization when only one reference exists, making the
50/// implementation as efficient as a mutable version.
51///
52/// Also note: in addition to the `From` traits described below, this module
53/// implements `From<Rope> for String` and `From<&Rope> for String`, for easy
54/// conversions in both directions.
55///
56/// # Examples
57///
58/// Create a `Rope` from a `String`:
59///
60/// ```rust
61/// # use xi_rope::Rope;
62/// let a = Rope::from("hello ");
63/// let b = Rope::from("world");
64/// assert_eq!("hello world", String::from(a.clone() + b.clone()));
65/// assert!("hello world" == String::from(a + b));
66/// ```
67///
68/// Get a slice of a `Rope`:
69///
70/// ```rust
71/// # use xi_rope::Rope;
72/// let a = Rope::from("hello world");
73/// let b = a.slice(1..9);
74/// assert_eq!("ello wor", String::from(&b));
75/// let c = b.slice(1..7);
76/// assert_eq!("llo wo", String::from(c));
77/// ```
78///
79/// Replace part of a `Rope`:
80///
81/// ```rust
82/// # use xi_rope::Rope;
83/// let mut a = Rope::from("hello world");
84/// a.edit(1..9, "era");
85/// assert_eq!("herald", String::from(a));
86/// ```
87pub type Rope = Node<RopeInfo>;
88
89/// Represents a transform from one rope to another.
90pub type RopeDelta = Delta<RopeInfo>;
91
92/// An element in a `RopeDelta`.
93pub type RopeDeltaElement = DeltaElement<RopeInfo>;
94
95impl Leaf for String {
96    fn len(&self) -> usize {
97        self.len()
98    }
99
100    fn is_ok_child(&self) -> bool {
101        self.len() >= MIN_LEAF
102    }
103
104    fn push_maybe_split(&mut self, other: &String, iv: Interval) -> Option<String> {
105        //println!("push_maybe_split [{}] [{}] {:?}", self, other, iv);
106        let (start, end) = iv.start_end();
107        self.push_str(&other[start..end]);
108        if self.len() <= MAX_LEAF {
109            None
110        } else {
111            let splitpoint = find_leaf_split_for_merge(self);
112            let right_str = self[splitpoint..].to_owned();
113            self.truncate(splitpoint);
114            self.shrink_to_fit();
115            Some(right_str)
116        }
117    }
118}
119
120#[derive(Clone, Copy)]
121pub struct RopeInfo {
122    lines: usize,
123    utf16_size: usize,
124}
125
126impl NodeInfo for RopeInfo {
127    type L = String;
128
129    fn accumulate(&mut self, other: &Self) {
130        self.lines += other.lines;
131        self.utf16_size += other.utf16_size;
132    }
133
134    fn compute_info(s: &String) -> Self {
135        RopeInfo { lines: count_newlines(s), utf16_size: count_utf16_code_units(s) }
136    }
137
138    fn identity() -> Self {
139        RopeInfo { lines: 0, utf16_size: 0 }
140    }
141}
142
143impl DefaultMetric for RopeInfo {
144    type DefaultMetric = BaseMetric;
145}
146
147//TODO: document metrics, based on https://github.com/google/xi-editor/issues/456
148//See ../docs/MetricsAndBoundaries.md for more information.
149/// This metric let us walk utf8 text by code point.
150///
151/// `BaseMetric` implements the trait [Metric].  Both its _measured unit_ and
152/// its _base unit_ are utf8 code unit.
153///
154/// Offsets that do not correspond to codepoint boundaries are _invalid_, and
155/// calling functions that assume valid offsets with invalid offets will panic
156/// in debug mode.
157///
158/// Boundary is atomic and determined by codepoint boundary.  Atomicity is
159/// implicit, because offsets between two utf8 code units that form a code
160/// point is considered invalid. For example, if a string starts with a
161/// 0xC2 byte, then `offset=1` is invalid.
162#[derive(Clone, Copy)]
163pub struct BaseMetric(());
164
165impl Metric<RopeInfo> for BaseMetric {
166    fn measure(_: &RopeInfo, len: usize) -> usize {
167        len
168    }
169
170    fn to_base_units(s: &String, in_measured_units: usize) -> usize {
171        debug_assert!(s.is_char_boundary(in_measured_units));
172        in_measured_units
173    }
174
175    fn from_base_units(s: &String, in_base_units: usize) -> usize {
176        debug_assert!(s.is_char_boundary(in_base_units));
177        in_base_units
178    }
179
180    fn is_boundary(s: &String, offset: usize) -> bool {
181        s.is_char_boundary(offset)
182    }
183
184    fn prev(s: &String, offset: usize) -> Option<usize> {
185        if offset == 0 {
186            // I think it's a precondition that this will never be called
187            // with offset == 0, but be defensive.
188            None
189        } else {
190            let mut len = 1;
191            while !s.is_char_boundary(offset - len) {
192                len += 1;
193            }
194            Some(offset - len)
195        }
196    }
197
198    fn next(s: &String, offset: usize) -> Option<usize> {
199        if offset == s.len() {
200            // I think it's a precondition that this will never be called
201            // with offset == s.len(), but be defensive.
202            None
203        } else {
204            let b = s.as_bytes()[offset];
205            Some(offset + len_utf8_from_first_byte(b))
206        }
207    }
208
209    fn can_fragment() -> bool {
210        false
211    }
212}
213
214/// Given the inital byte of a UTF-8 codepoint, returns the number of
215/// bytes required to represent the codepoint.
216/// RFC reference : https://tools.ietf.org/html/rfc3629#section-4
217pub fn len_utf8_from_first_byte(b: u8) -> usize {
218    match b {
219        b if b < 0x80 => 1,
220        b if b < 0xe0 => 2,
221        b if b < 0xf0 => 3,
222        _ => 4,
223    }
224}
225
226#[derive(Clone, Copy)]
227pub struct LinesMetric(usize); // number of lines
228
229/// Measured unit is newline amount.
230/// Base unit is utf8 code unit.
231/// Boundary is trailing and determined by a newline char.
232impl Metric<RopeInfo> for LinesMetric {
233    fn measure(info: &RopeInfo, _: usize) -> usize {
234        info.lines
235    }
236
237    fn is_boundary(s: &String, offset: usize) -> bool {
238        if offset == 0 {
239            // shouldn't be called with this, but be defensive
240            false
241        } else {
242            s.as_bytes()[offset - 1] == b'\n'
243        }
244    }
245
246    fn to_base_units(s: &String, in_measured_units: usize) -> usize {
247        let mut offset = 0;
248        for _ in 0..in_measured_units {
249            match memchr(b'\n', &s.as_bytes()[offset..]) {
250                Some(pos) => offset += pos + 1,
251                _ => panic!("to_base_units called with arg too large"),
252            }
253        }
254        offset
255    }
256
257    fn from_base_units(s: &String, in_base_units: usize) -> usize {
258        count_newlines(&s[..in_base_units])
259    }
260
261    fn prev(s: &String, offset: usize) -> Option<usize> {
262        debug_assert!(offset > 0, "caller is responsible for validating input");
263        memrchr(b'\n', &s.as_bytes()[..offset - 1]).map(|pos| pos + 1)
264    }
265
266    fn next(s: &String, offset: usize) -> Option<usize> {
267        memchr(b'\n', &s.as_bytes()[offset..]).map(|pos| offset + pos + 1)
268    }
269
270    fn can_fragment() -> bool {
271        true
272    }
273}
274
275#[derive(Clone, Copy)]
276pub struct Utf16CodeUnitsMetric(usize);
277
278impl Metric<RopeInfo> for Utf16CodeUnitsMetric {
279    fn measure(info: &RopeInfo, _: usize) -> usize {
280        info.utf16_size
281    }
282
283    fn is_boundary(s: &String, offset: usize) -> bool {
284        s.is_char_boundary(offset)
285    }
286
287    fn to_base_units(s: &String, in_measured_units: usize) -> usize {
288        let mut cur_len_utf16 = 0;
289        let mut cur_len_utf8 = 0;
290        for u in s.chars() {
291            if cur_len_utf16 >= in_measured_units {
292                break;
293            }
294            cur_len_utf16 += u.len_utf16();
295            cur_len_utf8 += u.len_utf8();
296        }
297        cur_len_utf8
298    }
299
300    fn from_base_units(s: &String, in_base_units: usize) -> usize {
301        count_utf16_code_units(&s[..in_base_units])
302    }
303
304    fn prev(s: &String, offset: usize) -> Option<usize> {
305        if offset == 0 {
306            // I think it's a precondition that this will never be called
307            // with offset == 0, but be defensive.
308            None
309        } else {
310            let mut len = 1;
311            while !s.is_char_boundary(offset - len) {
312                len += 1;
313            }
314            Some(offset - len)
315        }
316    }
317
318    fn next(s: &String, offset: usize) -> Option<usize> {
319        if offset == s.len() {
320            // I think it's a precondition that this will never be called
321            // with offset == s.len(), but be defensive.
322            None
323        } else {
324            let b = s.as_bytes()[offset];
325            Some(offset + len_utf8_from_first_byte(b))
326        }
327    }
328
329    fn can_fragment() -> bool {
330        false
331    }
332}
333
334// Low level functions
335
336pub fn count_newlines(s: &str) -> usize {
337    bytecount::count(s.as_bytes(), b'\n')
338}
339
340fn count_utf16_code_units(s: &str) -> usize {
341    let mut utf16_count = 0;
342    for &b in s.as_bytes() {
343        if (b as i8) >= -0x40 {
344            utf16_count += 1;
345        }
346        if b >= 0xf0 {
347            utf16_count += 1;
348        }
349    }
350    utf16_count
351}
352
353fn find_leaf_split_for_bulk(s: &str) -> usize {
354    find_leaf_split(s, MIN_LEAF)
355}
356
357fn find_leaf_split_for_merge(s: &str) -> usize {
358    find_leaf_split(s, max(MIN_LEAF, s.len() - MAX_LEAF))
359}
360
361// Try to split at newline boundary (leaning left), if not, then split at codepoint
362fn find_leaf_split(s: &str, minsplit: usize) -> usize {
363    let mut splitpoint = min(MAX_LEAF, s.len() - MIN_LEAF);
364    match memrchr(b'\n', &s.as_bytes()[minsplit - 1..splitpoint]) {
365        Some(pos) => minsplit + pos,
366        None => {
367            while !s.is_char_boundary(splitpoint) {
368                splitpoint -= 1;
369            }
370            splitpoint
371        }
372    }
373}
374
375// Additional APIs custom to strings
376
377impl FromStr for Rope {
378    type Err = ParseError;
379    fn from_str(s: &str) -> Result<Rope, Self::Err> {
380        let mut b = TreeBuilder::new();
381        b.push_str(s);
382        Ok(b.build())
383    }
384}
385
386impl Rope {
387    /// Edit the string, replacing the byte range [`start`..`end`] with `new`.
388    ///
389    /// Time complexity: O(log n)
390    #[deprecated(since = "0.3.0", note = "Use Rope::edit instead")]
391    pub fn edit_str<T: IntervalBounds>(&mut self, iv: T, new: &str) {
392        self.edit(iv, new)
393    }
394
395    /// Returns a new Rope with the contents of the provided range.
396    pub fn slice<T: IntervalBounds>(&self, iv: T) -> Rope {
397        self.subseq(iv)
398    }
399
400    // encourage callers to use Cursor instead?
401
402    /// Determine whether `offset` lies on a codepoint boundary.
403    pub fn is_codepoint_boundary(&self, offset: usize) -> bool {
404        let mut cursor = Cursor::new(self, offset);
405        cursor.is_boundary::<BaseMetric>()
406    }
407
408    /// Return the offset of the codepoint before `offset`.
409    pub fn prev_codepoint_offset(&self, offset: usize) -> Option<usize> {
410        let mut cursor = Cursor::new(self, offset);
411        cursor.prev::<BaseMetric>()
412    }
413
414    /// Return the offset of the codepoint after `offset`.
415    pub fn next_codepoint_offset(&self, offset: usize) -> Option<usize> {
416        let mut cursor = Cursor::new(self, offset);
417        cursor.next::<BaseMetric>()
418    }
419
420    /// Returns `offset` if it lies on a codepoint boundary. Otherwise returns
421    /// the codepoint after `offset`.
422    pub fn at_or_next_codepoint_boundary(&self, offset: usize) -> Option<usize> {
423        if self.is_codepoint_boundary(offset) {
424            Some(offset)
425        } else {
426            self.next_codepoint_offset(offset)
427        }
428    }
429
430    /// Returns `offset` if it lies on a codepoint boundary. Otherwise returns
431    /// the codepoint before `offset`.
432    pub fn at_or_prev_codepoint_boundary(&self, offset: usize) -> Option<usize> {
433        if self.is_codepoint_boundary(offset) {
434            Some(offset)
435        } else {
436            self.prev_codepoint_offset(offset)
437        }
438    }
439
440    pub fn prev_grapheme_offset(&self, offset: usize) -> Option<usize> {
441        let mut cursor = Cursor::new(self, offset);
442        cursor.prev_grapheme()
443    }
444
445    pub fn next_grapheme_offset(&self, offset: usize) -> Option<usize> {
446        let mut cursor = Cursor::new(self, offset);
447        cursor.next_grapheme()
448    }
449
450    /// Return the line number corresponding to the byte index `offset`.
451    ///
452    /// The line number is 0-based, thus this is equivalent to the count of newlines
453    /// in the slice up to `offset`.
454    ///
455    /// Time complexity: O(log n)
456    ///
457    /// # Panics
458    ///
459    /// This function will panic if `offset > self.len()`. Callers are expected to
460    /// validate their input.
461    pub fn line_of_offset(&self, offset: usize) -> usize {
462        self.count::<LinesMetric>(offset)
463    }
464
465    /// Return the byte offset corresponding to the line number `line`.
466    /// If `line` is equal to one plus the current number of lines,
467    /// this returns the offset of the end of the rope. Arguments higher
468    /// than this will panic.
469    ///
470    /// The line number is 0-based.
471    ///
472    /// Time complexity: O(log n)
473    ///
474    /// # Panics
475    ///
476    /// This function will panic if `line > self.measure::<LinesMetric>() + 1`.
477    /// Callers are expected to validate their input.
478    pub fn offset_of_line(&self, line: usize) -> usize {
479        let max_line = self.measure::<LinesMetric>() + 1;
480        if line > max_line {
481            panic!("line number {} beyond last line {}", line, max_line);
482        } else if line == max_line {
483            return self.len();
484        }
485        self.count_base_units::<LinesMetric>(line)
486    }
487
488    /// Returns an iterator over chunks of the rope.
489    ///
490    /// Each chunk is a `&str` slice borrowed from the rope's storage. The size
491    /// of the chunks is indeterminate but for large strings will generally be
492    /// in the range of 511-1024 bytes.
493    ///
494    /// The empty string will yield a single empty slice. In all other cases, the
495    /// slices will be nonempty.
496    ///
497    /// Time complexity: technically O(n log n), but the constant factor is so
498    /// tiny it is effectively O(n). This iterator does not allocate.
499    pub fn iter_chunks<T: IntervalBounds>(&self, range: T) -> ChunkIter {
500        let Interval { start, end } = range.into_interval(self.len());
501
502        ChunkIter { cursor: Cursor::new(self, start), end }
503    }
504
505    /// An iterator over the raw lines. The lines, except the last, include the
506    /// terminating newline.
507    ///
508    /// The return type is a `Cow<str>`, and in most cases the lines are slices
509    /// borrowed from the rope.
510    pub fn lines_raw<T: IntervalBounds>(&self, range: T) -> LinesRaw {
511        LinesRaw { inner: self.iter_chunks(range), fragment: "" }
512    }
513
514    /// An iterator over the lines of a rope.
515    ///
516    /// Lines are ended with either Unix (`\n`) or MS-DOS (`\r\n`) style line endings.
517    /// The line ending is stripped from the resulting string. The final line ending
518    /// is optional.
519    ///
520    /// The return type is a `Cow<str>`, and in most cases the lines are slices borrowed
521    /// from the rope.
522    ///
523    /// The semantics are intended to match `str::lines()`.
524    pub fn lines<T: IntervalBounds>(&self, range: T) -> Lines {
525        Lines { inner: self.lines_raw(range) }
526    }
527
528    // callers should be encouraged to use cursor instead
529    pub fn byte_at(&self, offset: usize) -> u8 {
530        let cursor = Cursor::new(self, offset);
531        let (leaf, pos) = cursor.get_leaf().unwrap();
532        leaf.as_bytes()[pos]
533    }
534
535    pub fn slice_to_cow<T: IntervalBounds>(&self, range: T) -> Cow<str> {
536        let mut iter = self.iter_chunks(range);
537        let first = iter.next();
538        let second = iter.next();
539
540        match (first, second) {
541            (None, None) => Cow::from(""),
542            (Some(s), None) => Cow::from(s),
543            (Some(one), Some(two)) => {
544                let mut result = [one, two].concat();
545                for chunk in iter {
546                    result.push_str(chunk);
547                }
548                Cow::from(result)
549            }
550            (None, Some(_)) => unreachable!(),
551        }
552    }
553}
554
555// should make this generic, but most leaf types aren't going to be sliceable
556pub struct ChunkIter<'a> {
557    cursor: Cursor<'a, RopeInfo>,
558    end: usize,
559}
560
561impl<'a> Iterator for ChunkIter<'a> {
562    type Item = &'a str;
563
564    fn next(&mut self) -> Option<&'a str> {
565        if self.cursor.pos() >= self.end {
566            return None;
567        }
568        let (leaf, start_pos) = self.cursor.get_leaf().unwrap();
569        let len = min(self.end - self.cursor.pos(), leaf.len() - start_pos);
570        self.cursor.next_leaf();
571        Some(&leaf[start_pos..start_pos + len])
572    }
573}
574
575impl TreeBuilder<RopeInfo> {
576    /// Push a string on the accumulating tree in the naive way.
577    ///
578    /// Splits the provided string in chunks that fit in a leaf
579    /// and pushes the leaves one by one onto the tree by calling.
580    pub fn push_str(&mut self, mut s: &str) {
581        if s.len() <= MAX_LEAF {
582            if !s.is_empty() {
583                self.push_leaf(s.to_owned());
584            }
585            return;
586        }
587        while !s.is_empty() {
588            let splitpoint = if s.len() > MAX_LEAF { find_leaf_split_for_bulk(s) } else { s.len() };
589            self.push_leaf(s[..splitpoint].to_owned());
590            s = &s[splitpoint..];
591        }
592    }
593
594    /// Push a string on the accumulating tree in an optimized fashion.
595    ///
596    /// Splits the string into leaves first and
597    /// then pushes all the leaves onto the accumulating tree in one go.
598    ///
599    /// Note: this is only used in tests.
600    #[doc(hidden)]
601    pub fn push_str_stacked(&mut self, s: &str) {
602        let leaves = split_as_leaves(s);
603        self.push_leaves(leaves);
604    }
605}
606
607fn split_as_leaves(mut s: &str) -> Vec<String> {
608    let mut nodes = Vec::new();
609    while !s.is_empty() {
610        let splitpoint = if s.len() > MAX_LEAF { find_leaf_split_for_bulk(s) } else { s.len() };
611        nodes.push(s[..splitpoint].to_owned());
612        s = &s[splitpoint..];
613    }
614    nodes
615}
616
617impl<T: AsRef<str>> From<T> for Rope {
618    fn from(s: T) -> Rope {
619        Rope::from_str(s.as_ref()).unwrap()
620    }
621}
622
623impl From<Rope> for String {
624    // maybe explore grabbing leaf? would require api in tree
625    fn from(r: Rope) -> String {
626        String::from(&r)
627    }
628}
629
630impl<'a> From<&'a Rope> for String {
631    fn from(r: &Rope) -> String {
632        r.slice_to_cow(..).into_owned()
633    }
634}
635
636impl fmt::Display for Rope {
637    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
638        for s in self.iter_chunks(..) {
639            write!(f, "{}", s)?;
640        }
641        Ok(())
642    }
643}
644
645impl fmt::Debug for Rope {
646    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
647        if f.alternate() {
648            write!(f, "{}", String::from(self))
649        } else {
650            write!(f, "Rope({:?})", String::from(self))
651        }
652    }
653}
654
655impl Add<Rope> for Rope {
656    type Output = Rope;
657    fn add(self, rhs: Rope) -> Rope {
658        let mut b = TreeBuilder::new();
659        b.push(self);
660        b.push(rhs);
661        b.build()
662    }
663}
664
665//additional cursor features
666
667impl<'a> Cursor<'a, RopeInfo> {
668    /// Get previous codepoint before cursor position, and advance cursor backwards.
669    pub fn prev_codepoint(&mut self) -> Option<char> {
670        self.prev::<BaseMetric>();
671        if let Some((l, offset)) = self.get_leaf() {
672            l[offset..].chars().next()
673        } else {
674            None
675        }
676    }
677
678    /// Get next codepoint after cursor position, and advance cursor.
679    pub fn next_codepoint(&mut self) -> Option<char> {
680        if let Some((l, offset)) = self.get_leaf() {
681            self.next::<BaseMetric>();
682            l[offset..].chars().next()
683        } else {
684            None
685        }
686    }
687
688    /// Get the next codepoint after the cursor position, without advancing
689    /// the cursor.
690    pub fn peek_next_codepoint(&self) -> Option<char> {
691        self.get_leaf().and_then(|(l, off)| l[off..].chars().next())
692    }
693
694    pub fn next_grapheme(&mut self) -> Option<usize> {
695        let (mut l, mut offset) = self.get_leaf()?;
696        let mut pos = self.pos();
697        while offset < l.len() && !l.is_char_boundary(offset) {
698            pos -= 1;
699            offset -= 1;
700        }
701        let mut leaf_offset = pos - offset;
702        let mut c = GraphemeCursor::new(pos, self.total_len(), true);
703        let mut next_boundary = c.next_boundary(&l, leaf_offset);
704        while let Err(incomp) = next_boundary {
705            if let GraphemeIncomplete::PreContext(_) = incomp {
706                let (pl, poffset) = self.prev_leaf()?;
707                c.provide_context(&pl, self.pos() - poffset);
708            } else if incomp == GraphemeIncomplete::NextChunk {
709                self.set(pos);
710                let (nl, noffset) = self.next_leaf()?;
711                l = nl;
712                leaf_offset = self.pos() - noffset;
713                pos = leaf_offset + nl.len();
714            } else {
715                return None;
716            }
717            next_boundary = c.next_boundary(&l, leaf_offset);
718        }
719        next_boundary.unwrap_or(None)
720    }
721
722    pub fn prev_grapheme(&mut self) -> Option<usize> {
723        let (mut l, mut offset) = self.get_leaf()?;
724        let mut pos = self.pos();
725        while offset < l.len() && !l.is_char_boundary(offset) {
726            pos += 1;
727            offset += 1;
728        }
729        let mut leaf_offset = pos - offset;
730        let mut c = GraphemeCursor::new(pos, l.len() + leaf_offset, true);
731        let mut prev_boundary = c.prev_boundary(&l, leaf_offset);
732        while let Err(incomp) = prev_boundary {
733            if let GraphemeIncomplete::PreContext(_) = incomp {
734                let (pl, poffset) = self.prev_leaf()?;
735                c.provide_context(&pl, self.pos() - poffset);
736            } else if incomp == GraphemeIncomplete::PrevChunk {
737                self.set(pos);
738                let (pl, poffset) = self.prev_leaf()?;
739                l = pl;
740                leaf_offset = self.pos() - poffset;
741                pos = leaf_offset + pl.len();
742            } else {
743                return None;
744            }
745            prev_boundary = c.prev_boundary(&l, leaf_offset);
746        }
747        prev_boundary.unwrap_or(None)
748    }
749}
750
751// line iterators
752
753pub struct LinesRaw<'a> {
754    inner: ChunkIter<'a>,
755    fragment: &'a str,
756}
757
758fn cow_append<'a>(a: Cow<'a, str>, b: &'a str) -> Cow<'a, str> {
759    if a.is_empty() {
760        Cow::from(b)
761    } else {
762        Cow::from(a.into_owned() + b)
763    }
764}
765
766impl<'a> Iterator for LinesRaw<'a> {
767    type Item = Cow<'a, str>;
768
769    fn next(&mut self) -> Option<Cow<'a, str>> {
770        let mut result = Cow::from("");
771        loop {
772            if self.fragment.is_empty() {
773                match self.inner.next() {
774                    Some(chunk) => self.fragment = chunk,
775                    None => return if result.is_empty() { None } else { Some(result) },
776                }
777                if self.fragment.is_empty() {
778                    // can only happen on empty input
779                    return None;
780                }
781            }
782            match memchr(b'\n', self.fragment.as_bytes()) {
783                Some(i) => {
784                    result = cow_append(result, &self.fragment[..=i]);
785                    self.fragment = &self.fragment[i + 1..];
786                    return Some(result);
787                }
788                None => {
789                    result = cow_append(result, self.fragment);
790                    self.fragment = "";
791                }
792            }
793        }
794    }
795}
796
797pub struct Lines<'a> {
798    inner: LinesRaw<'a>,
799}
800
801impl<'a> Iterator for Lines<'a> {
802    type Item = Cow<'a, str>;
803
804    fn next(&mut self) -> Option<Cow<'a, str>> {
805        match self.inner.next() {
806            Some(Cow::Borrowed(mut s)) => {
807                if s.ends_with('\n') {
808                    s = &s[..s.len() - 1];
809                    if s.ends_with('\r') {
810                        s = &s[..s.len() - 1];
811                    }
812                }
813                Some(Cow::from(s))
814            }
815            Some(Cow::Owned(mut s)) => {
816                if s.ends_with('\n') {
817                    let _ = s.pop();
818                    if s.ends_with('\r') {
819                        let _ = s.pop();
820                    }
821                }
822                Some(Cow::from(s))
823            }
824            None => None,
825        }
826    }
827}
828
829#[cfg(test)]
830mod tests {
831    use super::*;
832
833    #[test]
834    fn replace_small() {
835        let mut a = Rope::from("hello world");
836        a.edit(1..9, "era");
837        assert_eq!("herald", String::from(a));
838    }
839
840    #[test]
841    fn lines_raw_small() {
842        let a = Rope::from("a\nb\nc");
843        assert_eq!(vec!["a\n", "b\n", "c"], a.lines_raw(..).collect::<Vec<_>>());
844        assert_eq!(vec!["a\n", "b\n", "c"], a.lines_raw(..).collect::<Vec<_>>());
845
846        let a = Rope::from("a\nb\n");
847        assert_eq!(vec!["a\n", "b\n"], a.lines_raw(..).collect::<Vec<_>>());
848
849        let a = Rope::from("\n");
850        assert_eq!(vec!["\n"], a.lines_raw(..).collect::<Vec<_>>());
851
852        let a = Rope::from("");
853        assert_eq!(0, a.lines_raw(..).count());
854    }
855
856    #[test]
857    fn lines_small() {
858        let a = Rope::from("a\nb\nc");
859        assert_eq!(vec!["a", "b", "c"], a.lines(..).collect::<Vec<_>>());
860        assert_eq!(String::from(&a).lines().collect::<Vec<_>>(), a.lines(..).collect::<Vec<_>>());
861
862        let a = Rope::from("a\nb\n");
863        assert_eq!(vec!["a", "b"], a.lines(..).collect::<Vec<_>>());
864        assert_eq!(String::from(&a).lines().collect::<Vec<_>>(), a.lines(..).collect::<Vec<_>>());
865
866        let a = Rope::from("\n");
867        assert_eq!(vec![""], a.lines(..).collect::<Vec<_>>());
868        assert_eq!(String::from(&a).lines().collect::<Vec<_>>(), a.lines(..).collect::<Vec<_>>());
869
870        let a = Rope::from("");
871        assert_eq!(0, a.lines(..).count());
872        assert_eq!(String::from(&a).lines().collect::<Vec<_>>(), a.lines(..).collect::<Vec<_>>());
873
874        let a = Rope::from("a\r\nb\r\nc");
875        assert_eq!(vec!["a", "b", "c"], a.lines(..).collect::<Vec<_>>());
876        assert_eq!(String::from(&a).lines().collect::<Vec<_>>(), a.lines(..).collect::<Vec<_>>());
877
878        let a = Rope::from("a\rb\rc");
879        assert_eq!(vec!["a\rb\rc"], a.lines(..).collect::<Vec<_>>());
880        assert_eq!(String::from(&a).lines().collect::<Vec<_>>(), a.lines(..).collect::<Vec<_>>());
881    }
882
883    #[test]
884    fn lines_med() {
885        let mut a = String::new();
886        let mut b = String::new();
887        let line_len = MAX_LEAF + MIN_LEAF - 1;
888        for _ in 0..line_len {
889            a.push('a');
890            b.push('b');
891        }
892        a.push('\n');
893        b.push('\n');
894        let r = Rope::from(&a[..MAX_LEAF]);
895        let r = r + Rope::from(String::from(&a[MAX_LEAF..]) + &b[..MIN_LEAF]);
896        let r = r + Rope::from(&b[MIN_LEAF..]);
897        //println!("{:?}", r.iter_chunks().collect::<Vec<_>>());
898
899        assert_eq!(vec![a.as_str(), b.as_str()], r.lines_raw(..).collect::<Vec<_>>());
900        assert_eq!(vec![&a[..line_len], &b[..line_len]], r.lines(..).collect::<Vec<_>>());
901        assert_eq!(String::from(&r).lines().collect::<Vec<_>>(), r.lines(..).collect::<Vec<_>>());
902
903        // additional tests for line indexing
904        assert_eq!(a.len(), r.offset_of_line(1));
905        assert_eq!(r.len(), r.offset_of_line(2));
906        assert_eq!(0, r.line_of_offset(a.len() - 1));
907        assert_eq!(1, r.line_of_offset(a.len()));
908        assert_eq!(1, r.line_of_offset(r.len() - 1));
909        assert_eq!(2, r.line_of_offset(r.len()));
910    }
911
912    #[test]
913    fn append_large() {
914        let mut a = Rope::from("");
915        let mut b = String::new();
916        for i in 0..5_000 {
917            let c = i.to_string() + "\n";
918            b.push_str(&c);
919            a = a + Rope::from(&c);
920        }
921        assert_eq!(b, String::from(a));
922    }
923
924    #[test]
925    fn prev_codepoint_offset_small() {
926        let a = Rope::from("a\u{00A1}\u{4E00}\u{1F4A9}");
927        assert_eq!(Some(6), a.prev_codepoint_offset(10));
928        assert_eq!(Some(3), a.prev_codepoint_offset(6));
929        assert_eq!(Some(1), a.prev_codepoint_offset(3));
930        assert_eq!(Some(0), a.prev_codepoint_offset(1));
931        assert_eq!(None, a.prev_codepoint_offset(0));
932        let b = a.slice(1..10);
933        assert_eq!(Some(5), b.prev_codepoint_offset(9));
934        assert_eq!(Some(2), b.prev_codepoint_offset(5));
935        assert_eq!(Some(0), b.prev_codepoint_offset(2));
936        assert_eq!(None, b.prev_codepoint_offset(0));
937    }
938
939    #[test]
940    fn next_codepoint_offset_small() {
941        let a = Rope::from("a\u{00A1}\u{4E00}\u{1F4A9}");
942        assert_eq!(Some(10), a.next_codepoint_offset(6));
943        assert_eq!(Some(6), a.next_codepoint_offset(3));
944        assert_eq!(Some(3), a.next_codepoint_offset(1));
945        assert_eq!(Some(1), a.next_codepoint_offset(0));
946        assert_eq!(None, a.next_codepoint_offset(10));
947        let b = a.slice(1..10);
948        assert_eq!(Some(9), b.next_codepoint_offset(5));
949        assert_eq!(Some(5), b.next_codepoint_offset(2));
950        assert_eq!(Some(2), b.next_codepoint_offset(0));
951        assert_eq!(None, b.next_codepoint_offset(9));
952    }
953
954    #[test]
955    fn peek_next_codepoint() {
956        let inp = Rope::from("$¢€£💶");
957        let mut cursor = Cursor::new(&inp, 0);
958        assert_eq!(cursor.peek_next_codepoint(), Some('$'));
959        assert_eq!(cursor.peek_next_codepoint(), Some('$'));
960        assert_eq!(cursor.next_codepoint(), Some('$'));
961        assert_eq!(cursor.peek_next_codepoint(), Some('¢'));
962        assert_eq!(cursor.prev_codepoint(), Some('$'));
963        assert_eq!(cursor.peek_next_codepoint(), Some('$'));
964        assert_eq!(cursor.next_codepoint(), Some('$'));
965        assert_eq!(cursor.next_codepoint(), Some('¢'));
966        assert_eq!(cursor.peek_next_codepoint(), Some('€'));
967        assert_eq!(cursor.next_codepoint(), Some('€'));
968        assert_eq!(cursor.peek_next_codepoint(), Some('£'));
969        assert_eq!(cursor.next_codepoint(), Some('£'));
970        assert_eq!(cursor.peek_next_codepoint(), Some('💶'));
971        assert_eq!(cursor.next_codepoint(), Some('💶'));
972        assert_eq!(cursor.peek_next_codepoint(), None);
973        assert_eq!(cursor.next_codepoint(), None);
974        assert_eq!(cursor.peek_next_codepoint(), None);
975    }
976
977    #[test]
978    fn prev_grapheme_offset() {
979        // A with ring, hangul, regional indicator "US"
980        let a = Rope::from("A\u{030a}\u{110b}\u{1161}\u{1f1fa}\u{1f1f8}");
981        assert_eq!(Some(9), a.prev_grapheme_offset(17));
982        assert_eq!(Some(3), a.prev_grapheme_offset(9));
983        assert_eq!(Some(0), a.prev_grapheme_offset(3));
984        assert_eq!(None, a.prev_grapheme_offset(0));
985    }
986
987    #[test]
988    fn next_grapheme_offset() {
989        // A with ring, hangul, regional indicator "US"
990        let a = Rope::from("A\u{030a}\u{110b}\u{1161}\u{1f1fa}\u{1f1f8}");
991        assert_eq!(Some(3), a.next_grapheme_offset(0));
992        assert_eq!(Some(9), a.next_grapheme_offset(3));
993        assert_eq!(Some(17), a.next_grapheme_offset(9));
994        assert_eq!(None, a.next_grapheme_offset(17));
995    }
996
997    #[test]
998    fn next_grapheme_offset_with_ris_of_leaf_boundaries() {
999        let s1 = "\u{1f1fa}\u{1f1f8}".repeat(100);
1000        let a = Rope::concat(
1001            Rope::from(s1.clone()),
1002            Rope::concat(
1003                Rope::from(String::from(s1.clone()) + "\u{1f1fa}"),
1004                Rope::from(s1.clone()),
1005            ),
1006        );
1007        for i in 1..(s1.len() * 3) {
1008            assert_eq!(Some((i - 1) / 8 * 8), a.prev_grapheme_offset(i));
1009            assert_eq!(Some(i / 8 * 8 + 8), a.next_grapheme_offset(i));
1010        }
1011        for i in (s1.len() * 3 + 1)..(s1.len() * 3 + 4) {
1012            assert_eq!(Some(s1.len() * 3), a.prev_grapheme_offset(i));
1013            assert_eq!(Some(s1.len() * 3 + 4), a.next_grapheme_offset(i));
1014        }
1015        assert_eq!(None, a.prev_grapheme_offset(0));
1016        assert_eq!(Some(8), a.next_grapheme_offset(0));
1017        assert_eq!(Some(s1.len() * 3), a.prev_grapheme_offset(s1.len() * 3 + 4));
1018        assert_eq!(None, a.next_grapheme_offset(s1.len() * 3 + 4));
1019    }
1020
1021    #[test]
1022    fn line_of_offset_small() {
1023        let a = Rope::from("a\nb\nc");
1024        assert_eq!(0, a.line_of_offset(0));
1025        assert_eq!(0, a.line_of_offset(1));
1026        assert_eq!(1, a.line_of_offset(2));
1027        assert_eq!(1, a.line_of_offset(3));
1028        assert_eq!(2, a.line_of_offset(4));
1029        assert_eq!(2, a.line_of_offset(5));
1030        let b = a.slice(2..4);
1031        assert_eq!(0, b.line_of_offset(0));
1032        assert_eq!(0, b.line_of_offset(1));
1033        assert_eq!(1, b.line_of_offset(2));
1034    }
1035
1036    #[test]
1037    fn offset_of_line_small() {
1038        let a = Rope::from("a\nb\nc");
1039        assert_eq!(0, a.offset_of_line(0));
1040        assert_eq!(2, a.offset_of_line(1));
1041        assert_eq!(4, a.offset_of_line(2));
1042        assert_eq!(5, a.offset_of_line(3));
1043        let b = a.slice(2..4);
1044        assert_eq!(0, b.offset_of_line(0));
1045        assert_eq!(2, b.offset_of_line(1));
1046    }
1047
1048    #[test]
1049    fn eq_small() {
1050        let a = Rope::from("a");
1051        let a2 = Rope::from("a");
1052        let b = Rope::from("b");
1053        let empty = Rope::from("");
1054        assert!(a == a2);
1055        assert!(a != b);
1056        assert!(a != empty);
1057        assert!(empty == empty);
1058        assert!(a.slice(0..0) == empty);
1059    }
1060
1061    #[test]
1062    fn eq_med() {
1063        let mut a = String::new();
1064        let mut b = String::new();
1065        let line_len = MAX_LEAF + MIN_LEAF - 1;
1066        for _ in 0..line_len {
1067            a.push('a');
1068            b.push('b');
1069        }
1070        a.push('\n');
1071        b.push('\n');
1072        let r = Rope::from(&a[..MAX_LEAF]);
1073        let r = r + Rope::from(String::from(&a[MAX_LEAF..]) + &b[..MIN_LEAF]);
1074        let r = r + Rope::from(&b[MIN_LEAF..]);
1075
1076        let a_rope = Rope::from(&a);
1077        let b_rope = Rope::from(&b);
1078        assert!(r != a_rope);
1079        assert!(r.clone().slice(..a.len()) == a_rope);
1080        assert!(r.clone().slice(a.len()..) == b_rope);
1081        assert!(r == a_rope.clone() + b_rope.clone());
1082        assert!(r != b_rope + a_rope);
1083    }
1084
1085    #[test]
1086    fn line_offsets() {
1087        let rope = Rope::from("hi\ni'm\nfour\nlines");
1088        assert_eq!(rope.offset_of_line(0), 0);
1089        assert_eq!(rope.offset_of_line(1), 3);
1090        assert_eq!(rope.line_of_offset(0), 0);
1091        assert_eq!(rope.line_of_offset(3), 1);
1092        // interior of first line should be first line
1093        assert_eq!(rope.line_of_offset(1), 0);
1094        // interior of last line should be last line
1095        assert_eq!(rope.line_of_offset(15), 3);
1096        assert_eq!(rope.offset_of_line(4), rope.len());
1097    }
1098
1099    #[test]
1100    fn default_metric_test() {
1101        let rope = Rope::from("hi\ni'm\nfour\nlines\n");
1102        assert_eq!(
1103            rope.convert_metrics::<BaseMetric, LinesMetric>(rope.len()),
1104            rope.count::<LinesMetric>(rope.len())
1105        );
1106        assert_eq!(
1107            rope.convert_metrics::<LinesMetric, BaseMetric>(2),
1108            rope.count_base_units::<LinesMetric>(2)
1109        );
1110    }
1111
1112    #[test]
1113    #[should_panic]
1114    fn line_of_offset_panic() {
1115        let rope = Rope::from("hi\ni'm\nfour\nlines");
1116        rope.line_of_offset(20);
1117    }
1118
1119    #[test]
1120    #[should_panic]
1121    fn offset_of_line_panic() {
1122        let rope = Rope::from("hi\ni'm\nfour\nlines");
1123        rope.offset_of_line(5);
1124    }
1125
1126    #[test]
1127    fn utf16_code_units_metric() {
1128        let rope = Rope::from("hi\ni'm\nfour\nlines");
1129        let utf16_units = rope.measure::<Utf16CodeUnitsMetric>();
1130        assert_eq!(utf16_units, 17);
1131
1132        // position after 'f' in four
1133        let utf8_offset = 9;
1134        let utf16_units = rope.count::<Utf16CodeUnitsMetric>(utf8_offset);
1135        assert_eq!(utf16_units, 9);
1136
1137        let utf8_offset = rope.count_base_units::<Utf16CodeUnitsMetric>(utf16_units);
1138        assert_eq!(utf8_offset, 9);
1139
1140        let rope_with_emoji = Rope::from("hi\ni'm\n😀 four\nlines");
1141        let utf16_units = rope_with_emoji.measure::<Utf16CodeUnitsMetric>();
1142
1143        assert_eq!(utf16_units, 20);
1144
1145        // position after 'f' in four
1146        let utf8_offset = 13;
1147        let utf16_units = rope_with_emoji.count::<Utf16CodeUnitsMetric>(utf8_offset);
1148        assert_eq!(utf16_units, 11);
1149
1150        let utf8_offset = rope_with_emoji.count_base_units::<Utf16CodeUnitsMetric>(utf16_units);
1151        assert_eq!(utf8_offset, 13);
1152
1153        //for next line
1154        let utf8_offset = 19;
1155        let utf16_units = rope_with_emoji.count::<Utf16CodeUnitsMetric>(utf8_offset);
1156        assert_eq!(utf16_units, 17);
1157
1158        let utf8_offset = rope_with_emoji.count_base_units::<Utf16CodeUnitsMetric>(utf16_units);
1159        assert_eq!(utf8_offset, 19);
1160    }
1161
1162    #[test]
1163    fn slice_to_cow_small_string() {
1164        let short_text = "hi, i'm a small piece of text.";
1165
1166        let rope = Rope::from(short_text);
1167
1168        let cow = rope.slice_to_cow(..);
1169
1170        assert!(short_text.len() <= 1024);
1171        assert_eq!(cow, Cow::Borrowed(short_text) as Cow<str>);
1172    }
1173
1174    #[test]
1175    fn slice_to_cow_long_string_long_slice() {
1176        // 32 char long string, repeat it 33 times so it is longer than 1024 bytes
1177        let long_text =
1178            "1234567812345678123456781234567812345678123456781234567812345678".repeat(33);
1179
1180        let rope = Rope::from(&long_text);
1181
1182        let cow = rope.slice_to_cow(..);
1183
1184        assert!(long_text.len() > 1024);
1185        assert_eq!(cow, Cow::Owned(long_text) as Cow<str>);
1186    }
1187
1188    #[test]
1189    fn slice_to_cow_long_string_short_slice() {
1190        // 32 char long string, repeat it 33 times so it is longer than 1024 bytes
1191        let long_text =
1192            "1234567812345678123456781234567812345678123456781234567812345678".repeat(33);
1193
1194        let rope = Rope::from(&long_text);
1195
1196        let cow = rope.slice_to_cow(..500);
1197
1198        assert!(long_text.len() > 1024);
1199        assert_eq!(cow, Cow::Borrowed(&long_text[..500]));
1200    }
1201}
1202
1203#[cfg(all(test, feature = "serde"))]
1204mod serde_tests {
1205    use super::*;
1206    use crate::Rope;
1207    use serde_test::{assert_tokens, Token};
1208
1209    #[test]
1210    fn serialize_and_deserialize() {
1211        const TEST_LINE: &str = "test line\n";
1212
1213        // repeat test line enough times to exceed maximum leaf size
1214        let n_seg = MAX_LEAF / TEST_LINE.len() + 1;
1215        let test_str = TEST_LINE.repeat(n_seg);
1216
1217        let rope = Rope::from(test_str.as_str());
1218        let json = serde_json::to_string(&rope).expect("error serializing");
1219        let deserialized_rope =
1220            serde_json::from_str::<Rope>(json.as_str()).expect("error deserializing");
1221        assert_eq!(rope, deserialized_rope);
1222    }
1223
1224    #[test]
1225    fn test_ser_de() {
1226        let rope = Rope::from("a\u{00A1}\u{4E00}\u{1F4A9}");
1227        assert_tokens(&rope, &[Token::Str("a\u{00A1}\u{4E00}\u{1F4A9}")]);
1228        assert_tokens(&rope, &[Token::String("a\u{00A1}\u{4E00}\u{1F4A9}")]);
1229        assert_tokens(&rope, &[Token::BorrowedStr("a\u{00A1}\u{4E00}\u{1F4A9}")]);
1230    }
1231}