tenjin/
path.rs

1const SEP: char = '.';
2
3// Path
4
5#[derive(Clone, Copy, Debug)]
6pub enum Path<'a> {
7    End,
8    Pair(&'a str, &'a Path<'a>),
9}
10
11impl<'a> Path<'a> {
12    pub fn new(s: &str) -> Path {
13        Path::Pair(s, &Path::End)
14    }
15
16    pub fn parts(&self) -> Parts {
17        Parts { path: *self }
18    }
19
20    pub fn prepend(&'a self, first: &'a str) -> Path<'a> {
21        Path::Pair(first, self)
22    }
23
24    pub fn deconstruct(&self) -> Option<(&'a str, Path<'a>)> {
25        let mut node = self;
26
27        while let &Path::Pair(first, rest) = node {
28            let mut chars  = first.chars();
29            let mut substr = first;
30
31            while let Some(c) = chars.next() {
32                if c == SEP {
33                    substr = chars.as_str();
34                    continue;
35                }
36
37                return Some(
38                    if let Some(end) = substr.find(SEP) {
39                        let first  = &substr[..end];
40                        let second = &substr[end + SEP.len_utf8()..];
41                        (first, Path::Pair(second, rest))
42                    } else {
43                        (substr, *rest)
44                    }
45                );
46            }
47
48            node = rest;
49        }
50
51        None
52    }
53
54    pub fn to_owned(&self) -> PathBuf {
55        let mut buf = PathBuf::new();
56        let mut cur = self;
57
58        if let &Path::Pair(first, next) = cur {
59            buf.push_str(first);
60            cur = next;
61        } else {
62            return buf;
63        }
64
65        while let &Path::Pair(first, next) = cur {
66            buf.push(SEP);
67            buf.push_str(first);
68            cur = next;
69        }
70
71        buf
72    }
73}
74
75// Parts
76
77#[derive(Debug)]
78pub struct Parts<'a> {
79    path: Path<'a>,
80}
81
82impl<'a> Iterator for Parts<'a> {
83    type Item = &'a str;
84
85    fn next(&mut self) -> Option<Self::Item> {
86        let (res, path) = match self.path.deconstruct() {
87            Some((res, path)) => (Some(res), path),
88            None => (None, Path::End),
89        };
90
91        self.path = path;
92        res
93    }
94}
95
96impl<'a> Parts<'a> {
97    pub fn as_path(&self) -> Path {
98        self.path
99    }
100}
101
102// PathBuf
103
104pub type PathBuf = String;