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
use std::collections::LinkedList;
use std::fs::File;
use std::io::BufWriter;
use std::path::Path;
use std::path::PathBuf;
use serde::Serialize;
use crate::format::Error;
#[allow(unused)]
pub fn write_json<O: ?Sized + Serialize, P: AsRef<Path>>(path: P, val: &O) -> Result<(), Error> {
let file = File::create(path.as_ref()).map_err(Error::Io)?;
let writer = BufWriter::new(file);
serde_json::to_writer(writer, val)
.map_err(Error::Serde)
}
#[allow(unused)]
pub fn write_table<O, Header, Rows, RowItem>(out: &mut O, header: Header, rows: Rows) -> Result<(), std::io::Error>
where O: std::io::Write,
Rows: IntoIterator<Item=RowItem>,
RowItem: IntoIterator<Item=String>,
Header: IntoIterator<Item=String> {
{
let mut lengths: Vec<usize> = header.into_iter().map(|s| s.len() + 2).collect();
let rows = rows
.into_iter()
.map(|v| v.into_iter())
.map(|v| v.collect::<Vec<_>>())
.map(|v| {
assert_eq!(v.len(), lengths.len());
for (i, v) in v.iter().enumerate() {
lengths[i] = std::cmp::max(lengths[i], v.len() + 2);
}
v
})
.collect::<Vec<_>>();
write!(out, "┌");
for (i, len) in lengths.iter().enumerate() {
if i > 0 {
write!(out, "┬");
}
write!(out, "{:─<1$}", "─", len + 2);
}
writeln!(out, "┐");
for (i, row) in rows.iter().enumerate() {
if i > 0 {
write!(out, "├");
for (i, len) in lengths.iter().enumerate() {
if i > 0 {
write!(out, "┼");
}
write!(out, "{:─<1$}", "─", len + 2);
}
writeln!(out, "┤");
}
write!(out, "│");
for (i, row) in row.iter().enumerate() {
if i > 0 {
write!(out, "│");
}
write!(out, " {:<1$}", row, lengths[i] + 1);
}
writeln!(out, "│");
}
write!(out, "└");
for (i, len) in lengths.iter().enumerate() {
if i > 0 {
write!(out, "┴");
}
write!(out, "{:─<1$}", "─", len + 2);
}
writeln!(out, "┘");
Ok(())
}
}
pub trait RecurseDir<T> {
fn matches(&self, path: &PathBuf) -> Option<T>;
fn recurse_dir<O, I: FromIterator<O>, F: Fn(PathBuf, T) -> O>(&self, path: PathBuf, visitor: F) -> I {
let mut queue = LinkedList::new();
queue.push_back(path);
let mut vals = LinkedList::new();
while let Some(next) = queue.pop_front() {
if next.is_dir() {
let entry = next.read_dir().unwrap();
for e in entry {
let e = e.unwrap();
if e.path().is_dir() {
queue.push_back(e.path());
} else {
let path = e.path();
if let Some(val) = self.matches(&path) {
vals.push_back(visitor(path, val));
}
}
}
} else {
if let Some(val) = self.matches(&next) {
vals.push_back(visitor(next, val));
}
}
}
I::from_iter(vals.into_iter())
}
}