1use 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
38pub type Rope = Node<RopeInfo>;
88
89pub type RopeDelta = Delta<RopeInfo>;
91
92pub 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 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#[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 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 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
214pub 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); impl 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 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 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 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
334pub 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
361fn 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
375impl 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 #[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 pub fn slice<T: IntervalBounds>(&self, iv: T) -> Rope {
397 self.subseq(iv)
398 }
399
400 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 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 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 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 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 pub fn line_of_offset(&self, offset: usize) -> usize {
462 self.count::<LinesMetric>(offset)
463 }
464
465 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 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 pub fn lines_raw<T: IntervalBounds>(&self, range: T) -> LinesRaw {
511 LinesRaw { inner: self.iter_chunks(range), fragment: "" }
512 }
513
514 pub fn lines<T: IntervalBounds>(&self, range: T) -> Lines {
525 Lines { inner: self.lines_raw(range) }
526 }
527
528 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
555pub 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 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 #[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 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
665impl<'a> Cursor<'a, RopeInfo> {
668 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 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 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
751pub 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 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 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 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 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 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 assert_eq!(rope.line_of_offset(1), 0);
1094 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 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 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 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 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 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 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}