diff options
| -rw-r--r-- | src/main.rs | 21 | ||||
| -rw-r--r-- | src/rope.rs | 96 |
2 files changed, 116 insertions, 1 deletions
diff --git a/src/main.rs b/src/main.rs index e7a11a9..5302d59 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,22 @@ +mod rope; + +use rope::Rope; +use std::ffi::OsString; +use std::path::Path; + fn main() { - println!("Hello, world!"); + let args: Vec<OsString> = std::env::args_os().collect(); + if args.len() != 2 { + println!("Usage: edit <filename>"); + std::process::exit(1); + } + let file = Path::new(&args[1]); + let r = match Rope::open(file) { + Ok(r) => r, + Err(err) => { + println!("FAIL: open file {}: {}", file.to_string_lossy(), err); + std::process::exit(1); + } + }; + println!("{}", r); } diff --git a/src/rope.rs b/src/rope.rs new file mode 100644 index 0000000..437d5e3 --- /dev/null +++ b/src/rope.rs @@ -0,0 +1,96 @@ +use std::fmt::{Display, Error, Formatter}; +use std::fs::File; +use std::io::{ErrorKind, Read}; +use std::path::Path; +use std::rc::Rc; + +const MAX_NODE_SIZE: usize = 512; + +struct Branch { + len: usize, + left: Rc<Node>, + right: Rc<Node>, +} + +enum Node { + Leaf(Vec<u8>), + Branch(Branch), +} + +impl Display for Node { + fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { + match self { + Node::Leaf(s) => { + return write!(f, "{}", String::from_utf8_lossy(s)); + } + Node::Branch(b) => { + if let Err(err) = write!(f, "{}", b.left) { + return Err(err); + } + return write!(f, "{}", b.right); + } + } + } +} + +impl Node { + fn len(&self) -> usize { + return match self { + Node::Leaf(v) => v.len(), + Node::Branch(b) => b.len, + }; + } +} + +pub struct Rope(Rc<Node>); + +impl Display for Rope { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { + let Rope(n) = self; + return write!(f, "{}", n); + } +} + +impl Rope { + fn concat(self, Rope(other): Rope) -> Rope { + let Rope(me) = self; + if me.len() == 0 { + return Rope(other); + } + if other.len() == 0 { + return Rope(me); + } + return Rope(Rc::new(Node::Branch(Branch { + len: me.len() + other.len(), + left: me, + right: other, + }))); + } + + pub fn open(path: &Path) -> Result<Rope, String> { + let mut f = match File::open(path) { + Ok(f) => f, + Err(err) => { + return Err(format!("open: {}", err)); + } + }; + let mut rope = Rope(Rc::new(Node::Leaf(vec![]))); + loop { + let mut buf = vec![0; MAX_NODE_SIZE]; + let n = match f.read(&mut buf) { + Ok(n) => n, + Err(err) => { + if err.kind() == ErrorKind::Interrupted { + continue; + } + return Err(format!("read: {}", err)); + } + }; + if n == 0 { + break; + } + rope = rope.concat(Rope(Rc::new(Node::Leaf(buf)))); + } + return Ok(rope); + } +} |
