1use std::ops::{Deref, DerefMut};
2
3#[doc(hidden)]
7#[derive(Debug, Default, Clone, Eq, PartialEq)]
8pub struct Rope(crop::Rope);
9
10#[doc(hidden)]
14pub use crop::RopeSlice;
15
16impl Deref for Rope {
17 type Target = crop::Rope;
18
19 fn deref(&self) -> &Self::Target {
20 &self.0
21 }
22}
23
24impl DerefMut for Rope {
25 fn deref_mut(&mut self) -> &mut Self::Target {
26 &mut self.0
27 }
28}
29
30impl From<crop::Rope> for Rope {
31 fn from(rope: crop::Rope) -> Self {
32 Self(rope)
33 }
34}
35
36impl From<Rope> for crop::Rope {
37 fn from(rope: Rope) -> Self {
38 rope.0
39 }
40}
41
42impl From<&str> for Rope {
43 fn from(s: &str) -> Self {
44 Self(crop::Rope::from(s))
45 }
46}
47
48impl From<String> for Rope {
49 fn from(s: String) -> Self {
50 Self(crop::Rope::from(s))
51 }
52}
53
54impl Rope {
55 pub fn line_column_of_byte(&self, byte_offset: usize) -> (usize, usize) {
56 self.byte_slice(..).line_column_of_byte(byte_offset)
57 }
58}
59
60#[doc(hidden)]
64pub trait RopeSliceExt {
65 fn eq_str(&self, s: &str) -> bool;
66 fn line_column_of_byte(&self, byte_offset: usize) -> (usize, usize);
67}
68
69impl RopeSliceExt for RopeSlice<'_> {
70 fn eq_str(&self, s: &str) -> bool {
71 let mut this = self.bytes();
72 let mut s = s.as_bytes().iter();
73
74 loop {
75 match (this.next(), s.next()) {
76 (Some(this_byte), Some(s_byte)) => {
77 if this_byte != *s_byte {
78 return false;
79 }
80 continue;
81 }
82 (None, None) => return true,
83 _ => return false,
84 }
85 }
86 }
87
88 fn line_column_of_byte(&self, byte_offset: usize) -> (usize, usize) {
89 let line = self.line_of_byte(byte_offset);
90 let start_of_line = self.byte_of_line(line);
91 let column = byte_offset - start_of_line;
92 (line, column)
93 }
94}
95
96#[cfg(test)]
97mod tests {
98 use crate::rope::{Rope, RopeSliceExt as _};
99
100 #[test]
101 fn test_eq_str() {
102 let rope = Rope::from("hello world");
103 assert!(rope.byte_slice(0..5).eq_str("hello"));
104 assert!(rope.byte_slice(6..11).eq_str("world"));
105 assert!(rope.byte_slice(..).eq_str("hello world"));
106 assert!(!rope.byte_slice(0..4).eq_str("hello"));
107 assert!(!rope.byte_slice(0..5).eq_str("world"));
108 assert!(!rope.byte_slice(6..11).eq_str("hello worlds"));
109 }
110}