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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use std::fmt;
use super::{Resources, Directory, Entry};
#[derive(Debug)]
struct Art {
margin_draw: &'static str,
margin_open: &'static str,
dir_entry: &'static str,
dir_tail: &'static str,
file_entry: &'static str,
file_tail: &'static str,
}
static U: Art = Art {
margin_draw: "│ ",
margin_open: " ",
dir_entry: "├── ",
dir_tail: "└── ",
file_entry: "├── ",
file_tail: "└── ",
};
static A: Art = Art {
margin_draw: "| ",
margin_open: " ",
dir_entry: "+-- ",
dir_tail: "`-- ",
file_entry: "+-- ",
file_tail: "`-- ",
};
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[allow(dead_code)]
enum TreeArt {
Ascii,
Unicode,
}
#[derive(Clone, Debug)]
struct TreeFmt<'a: 'd, 'd> {
dir: &'d Directory<'a>,
art: &'static Art,
depth: u32,
margin: u32,
}
impl<'a, 'd> TreeFmt<'a, 'd> {
fn root(root: &'d Directory<'a>, art: TreeArt) -> TreeFmt<'a, 'd> {
let art = match art {
TreeArt::Ascii => &A,
TreeArt::Unicode => &U,
};
TreeFmt { dir: root, art, depth: !0, margin: 0 }
}
fn dir(dir: &'d Directory<'a>, art: TreeArt) -> TreeFmt<'a, 'd> {
let art = match art {
TreeArt::Ascii => &A,
TreeArt::Unicode => &U,
};
TreeFmt { dir, art, depth: 0, margin: 0 }
}
fn draw<F: fmt::Write>(&self, f: &mut F) -> fmt::Result {
let (root, depth) = if self.depth == !0 { (true, 0) } else { (false, self.depth) };
if depth >= 32 {
return Ok(());
}
let mut entries = self.dir.entries();
while let Some(e) = entries.next() {
for open in (0..depth).map(|i| self.margin & (1 << i) != 0) {
f.write_str(if open { self.art.margin_open } else { self.art.margin_draw })?;
}
let tail = entries.len() == 0;
let prefix = match (tail, e.is_dir()) {
(false, false) => self.art.file_entry,
(true, false) => self.art.file_tail,
(false, true) => self.art.dir_entry,
(true, true) => self.art.dir_tail,
};
f.write_str(prefix)?;
match e.name() {
Ok(name) => write!(f, "{}", name.rename_id(if root { &super::RSRC_TYPES } else { &[] })),
Err(err) => write!(f, "{}", err),
}.and_then(|_| {
f.write_str(if e.is_dir() { "/\n" } else { "\n" })
})?;
if let Ok(Entry::Directory(dir)) = e.entry() {
TreeFmt {
dir: &dir,
art: self.art,
depth: depth + 1,
margin: self.margin | (tail as u32) << depth,
}.draw(f)?;
}
}
Ok(())
}
}
impl<'a> fmt::Display for Resources<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("Resources/\n")?;
match self.root() {
Ok(root) => TreeFmt::root(&root, TreeArt::Ascii).draw(f),
Err(err) => err.fmt(f),
}
}
}
impl<'a> fmt::Display for Directory<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("Directory/\n")?;
TreeFmt::dir(self, TreeArt::Ascii).draw(f)
}
}