aboutsummaryrefslogtreecommitdiffstats
path: root/src/rope.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/rope.rs')
-rw-r--r--src/rope.rs54
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)));
+ }
}