-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
build.rs
129 lines (117 loc) · 3.08 KB
/
build.rs
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
124
125
126
127
128
129
/*!
# pxsum: Build Script
*/
use argyle::KeyWordsBuilder;
use dactyl::NiceU32;
use image::ImageFormat;
use std::{
collections::BTreeSet,
io::Write,
path::PathBuf,
};
/// # Pre-Compute CLI keys and Extensions.
pub fn main() {
build_cli();
build_ext();
}
/// # Build CLI Keys.
fn build_cli() {
let mut builder = KeyWordsBuilder::default();
builder.push_keys([
"--bench",
"-c", "--check",
"-g", "--group-by-checksum",
"-h", "--help",
"--no-warnings",
"--only-dupes",
"-q", "--quiet",
"--strict",
"-V", "--version",
]);
builder.push_keys_with_values([
"-d", "--dir",
"-j"
]);
builder.save(out_path("argyle.rs"));
}
/// # Build Extensions.
fn build_ext() {
// Collect the supported formats.
let formats: Vec<ImageFormat> = ImageFormat::all()
.filter(|f| f.can_read() && f.reading_enabled())
.collect();
// Build up a list of matching file extensions by length.
let mut ext3: BTreeSet<u32> = BTreeSet::new();
let mut ext4: BTreeSet<u32> = BTreeSet::new();
for f in formats {
for ext in f.extensions_str() {
assert!(ext.is_ascii(), "Bug: extension is non-ascii: {ext}");
match ext.as_bytes() {
[a, b, c] => {
ext3.insert(u32::from_le_bytes([
b'.',
a.to_ascii_lowercase(),
b.to_ascii_lowercase(),
c.to_ascii_lowercase(),
]));
},
[a, b, c, d] => {
ext4.insert(u32::from_le_bytes([
a.to_ascii_lowercase(),
b.to_ascii_lowercase(),
c.to_ascii_lowercase(),
d.to_ascii_lowercase(),
]));
},
_ => panic!("Bug: file extension has unexpected length: {ext}"),
}
}
}
// Formats not in the image crate.
ext3.insert(u32::from_le_bytes(*b".j2c"));
ext3.insert(u32::from_le_bytes(*b".j2k"));
ext3.insert(u32::from_le_bytes(*b".jp2"));
ext3.insert(u32::from_le_bytes(*b".jpc"));
ext3.insert(u32::from_le_bytes(*b".jxl"));
ext4.insert(u32::from_le_bytes(*b"avif"));
ext4.insert(u32::from_le_bytes(*b"jpg2"));
// Build up a matching method we can use at runtime.
let out = format!(
r"
/// # Match Image Extension.
const fn check_extension(bytes: &[u8]) -> bool {{
if let [.., 0..=46 | 48..=91 | 93..=255, b'.', a, b, c] = bytes {{
matches!(
u32::from_le_bytes([b'.', a.to_ascii_lowercase(), b.to_ascii_lowercase(), c.to_ascii_lowercase()]),
{}
)
}}
else if let [.., 0..=46 | 48..=91 | 93..=255, b'.', a, b, c, d] = bytes {{
matches!(
u32::from_le_bytes([a.to_ascii_lowercase(), b.to_ascii_lowercase(), c.to_ascii_lowercase(), d.to_ascii_lowercase()]),
{}
)
}}
else {{ false }}
}}",
ext3.into_iter()
.map(|n| NiceU32::with_separator(n, b'_'))
.collect::<Vec<_>>()
.join(" | "),
ext4.into_iter()
.map(|n| NiceU32::with_separator(n, b'_'))
.collect::<Vec<_>>()
.join(" | "),
);
std::fs::File::create(out_path("pxsum-ext.rs"))
.and_then(|mut f| f.write_all(out.as_bytes()).and_then(|_| f.flush()))
.expect("Unable to write file.");
}
/// # Output Path.
///
/// Append the sub-path to OUT_DIR and return it.
fn out_path(stub: &str) -> PathBuf {
std::fs::canonicalize(std::env::var("OUT_DIR").expect("Missing OUT_DIR."))
.expect("Missing OUT_DIR.")
.join(stub)
}