use std::fmt::{Display, Error, Formatter}; use std::fs::File; use std::io::{ErrorKind, Read}; use std::path::Path; use std::rc::Rc; // Set to a small value to help identify bugs in the implementation. const MAX_NODE_SIZE: usize = 4; struct Branch { left: Rc, right: Rc, } enum Node { Leaf(Vec), Branch(Branch), } impl Node { fn write(&self, out: &mut Vec) { match self { Node::Leaf(v) => { out.extend(v); } Node::Branch(b) => { b.left.write(out); b.right.write(out); } } } fn empty(&self) -> bool { return match self { Node::Leaf(v) => v.len() == 0, _ => false, }; } } impl Display for Node { fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { let mut buf = Vec::new(); self.write(&mut buf); return write!(f, "{}", String::from_utf8_lossy(&buf)); } } pub struct Rope(Rc); impl Rope { fn concat(self, Rope(other): Rope) -> Rope { let Rope(me) = self; if me.empty() { return Rope(other); } if other.empty() { return Rope(me); } return Rope(Rc::new(Node::Branch(Branch { left: me, right: other, }))); } pub fn open(path: &Path) -> Result { 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); } } impl Display for Rope { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { let Rope(n) = self; return write!(f, "{}", n); } }