diff options
Diffstat (limited to 'src/rope.rs')
| -rw-r--r-- | src/rope.rs | 85 |
1 files changed, 81 insertions, 4 deletions
diff --git a/src/rope.rs b/src/rope.rs index 320cd14..b1b5831 100644 --- a/src/rope.rs +++ b/src/rope.rs @@ -1,6 +1,6 @@ -use std::fmt::{Display, Error, Formatter}; +use std::fmt::{Display, Formatter}; use std::fs::File; -use std::io::{ErrorKind, Read}; +use std::io::{ErrorKind, Read, Write}; use std::path::Path; use std::rc::Rc; @@ -10,6 +10,8 @@ const MAX_NODE_SIZE: usize = 4; struct Branch { left: Rc<Node>, right: Rc<Node>, + // Number of newline characters under this branch. + lines: usize, } enum Node { @@ -36,10 +38,73 @@ impl Node { _ => false, }; } + + fn lines(&self) -> usize { + match self { + Node::Leaf(v) => { + let mut count = 0; + for &c in v { + if c == b'\n' { + count += 1; + } + } + return count; + } + Node::Branch(b) => { + return b.lines; + } + } + } + + fn print_lines( + &self, + out: &mut dyn Write, + start: usize, + end: usize, + ) -> Result<(), std::io::Error> { + match self { + Node::Leaf(v) => { + let mut nl_count = 0; + let mut start_pos = 0; + let mut end_pos = v.len(); + for (i, &c) in v.iter().enumerate() { + if c != b'\n' { + continue; + } + nl_count += 1; + if nl_count == start { + start_pos = i; + } + if nl_count == end { + end_pos = i + 1; + } + } + if let Err(err) = out.write(&v[start_pos..end_pos]) { + return Err(err); + } + return Ok(()); + } + Node::Branch(b) => { + let right_start; + if start <= b.left.lines() { + if let Err(err) = b.left.print_lines(out, start, end) { + return Err(err); + } + right_start = 0; + } else { + right_start = start - b.left.lines(); + } + if end <= b.left.lines() { + return Ok(()); + } + return b.right.print_lines(out, right_start, end - b.left.lines()); + } + } + } } impl Display for Node { - fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), std::fmt::Error> { let mut buf = Vec::new(); self.write(&mut buf); return write!(f, "{}", String::from_utf8_lossy(&buf)); @@ -57,9 +122,11 @@ impl Rope { if other.empty() { return Rope(me); } + let lines = me.lines() + other.lines(); return Rope(Rc::new(Node::Branch(Branch { left: me, right: other, + lines: lines, }))); } @@ -89,10 +156,20 @@ impl Rope { } return Ok(rope); } + + pub fn print_lines( + &self, + out: &mut dyn Write, + start: usize, + end: usize, + ) -> Result<(), std::io::Error> { + let Rope(me) = self; + return me.print_lines(out, start, end); + } } impl Display for Rope { - fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { let Rope(n) = self; return write!(f, "{}", n); } |
