diff options
Diffstat (limited to 'src/rope.rs')
| -rw-r--r-- | src/rope.rs | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/src/rope.rs b/src/rope.rs index 3162e44..7d5ee28 100644 --- a/src/rope.rs +++ b/src/rope.rs @@ -132,6 +132,55 @@ impl Node { } } } + + fn insert(&self, pos: usize, c: u8) -> Node { + match self { + Node::Leaf(v) => { + if v.len() < MAX_NODE_SIZE { + let mut new_buf = vec![0; v.len() + 1]; + new_buf[..pos].copy_from_slice(&v[..pos]); + new_buf[pos] = c; + new_buf[pos + 1..].copy_from_slice(&v[pos..]); + return Node::Leaf(new_buf); + } + let mut buf_left = vec![0; pos + 1]; + buf_left[..pos].copy_from_slice(&v[..pos]); + buf_left[pos] = c; + let mut buf_right = Vec::new(); + buf_right.extend_from_slice(&v[pos..]); + let mut lines = self.lines(); + if c == b'\n' { + lines += 1; + } + return Node::Branch(Branch { + left: Rc::new(Node::Leaf(buf_left)), + right: Rc::new(Node::Leaf(buf_right)), + len: v.len() + 1, + lines: lines, + }); + } + Node::Branch(b) => { + let mut lines = self.lines(); + if c == b'\n' { + lines += 1; + } + if pos < b.left.len() { + return Node::Branch(Branch { + left: Rc::new(b.left.insert(pos, c)), + right: b.right.clone(), + len: b.len + 1, + lines: lines, + }); + } + return Node::Branch(Branch { + left: b.left.clone(), + right: Rc::new(b.right.insert(pos - b.left.len(), c)), + len: b.len + 1, + lines: lines, + }); + } + } + } } impl Display for Node { @@ -251,4 +300,9 @@ impl Slice { pub fn len(&self) -> usize { return self.end - self.start; } + + pub fn insert(&self, pos: usize, c: u8) -> Rope { + let Rope(buf) = &self.buf; + return Rope(Rc::new(buf.insert(self.start + pos, c))); + } } |
