aboutsummaryrefslogtreecommitdiffstats
path: root/src/rope.rs
blob: 437d5e3d52e3c73210a65c87b7d39ebee3d16623 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
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);
    }
}