-
Notifications
You must be signed in to change notification settings - Fork 10
/
build.rs
99 lines (87 loc) · 3.44 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
use regex_automata::{
dfa::{dense, StartKind},
nfa::{thompson, thompson::WhichCaptures},
util::prefilter::Prefilter,
util::syntax,
MatchKind,
};
use std::{fs, io};
const MAC_ADDR_REGEX_STR: &str = "^(?:(?:[0-9A-Fa-f]{2}:){5}|(?:[0-9A-Fa-f]{2}-){5})[0-9A-Fa-f]{2}$";
fn main() -> io::Result<()> {
#[cfg(windows)]
{
embed_resource::compile("icon.rc", embed_resource::NONE);
}
let mac_addr_validation_dir = "src/mac_address/validation";
fs::create_dir_all(mac_addr_validation_dir).unwrap();
let nfa_config = thompson::NFA::config()
.which_captures(WhichCaptures::None)
.utf8(false)
.shrink(true)
.reverse(false);
let pre = Prefilter::new(MatchKind::LeftmostFirst, &["[[:xdigit:]]"]);
//dbg!(pre.clone().unwrap().is_fast());
let dense_dfa = dense::DFA::builder()
.syntax(syntax::Config::new().unicode(false).utf8(false))
.thompson(nfa_config.clone())
.configure(
dense::DFA::config()
.start_kind(StartKind::Anchored)
.prefilter(pre)
.minimize(true),
)
.build(MAC_ADDR_REGEX_STR)
.expect("dense DFA");
// Write the contents of the DFA *without* the initial padding.
let (bytes, pad) = dense_dfa.to_bytes_big_endian();
std::fs::write(
format!("{mac_addr_validation_dir}/mac_addr_regex.bigendian.dfa"),
&bytes[pad..],
)
.unwrap();
// Do it again, but this time for little endian.
let (bytes, pad) = dense_dfa.to_bytes_little_endian();
std::fs::write(
format!("{mac_addr_validation_dir}/mac_addr_regex.littleendian.dfa"),
&bytes[pad..],
)
.unwrap();
let autogenerated_mod_header = "\
// DO NOT EDIT THIS FILE. IT WAS AUTOMATICALLY GENERATED BY THE BUILD SCRIPT\n\n\
use once_cell::sync::Lazy;\n\
use regex_automata::{\n\
\tdfa::{dense, Automaton},\n\
\tutil::wire::AlignAs,\n\
\tAnchored, Input,\n\
};\n\
\n";
let const_regex_str = format!(r#"pub(crate) const MAC_ADDR_REGEX_STR: &str = "{MAC_ADDR_REGEX_STR}";"#);
let autogenerated_mod_body = "\n\n\
pub static MAC_ADDR_REGEX: Lazy<dense::DFA<&'static [u32]>> = Lazy::new(|| {\n\
\tstatic ALIGNED: &AlignAs<[u8], u32> = &AlignAs {\n\
\t\t_align: [],\n\
\t\t#[cfg(target_endian = \"big\")]\n\
\t\tbytes: *include_bytes!(\"mac_addr_regex.bigendian.dfa\"),\n\
\t\t#[cfg(target_endian = \"little\")]\n\
\t\tbytes: *include_bytes!(\"mac_addr_regex.littleendian.dfa\"),\n\
\t};\n\
\tlet (dense_dfa, _) = dense::DFA::from_bytes(&ALIGNED.bytes)\
.expect(\"serialized dense::DFA should be valid\");\n\
\tdense_dfa\n\
});\n\
\n\
pub(crate) fn text_is_valid_mac<S: AsRef<[u8]>>(bytes: S) -> bool {\n\
\tMAC_ADDR_REGEX\n\
\t\t.try_search_fwd(&Input::new(&bytes).anchored(Anchored::Yes).earliest(true))\n\
\t\t.map_or(false, |x| x.is_some())\n\
}";
let autogenerated_mod_string = format!("{autogenerated_mod_header}{const_regex_str}{autogenerated_mod_body}");
fs::write(
format!("{mac_addr_validation_dir}/mod.rs"),
autogenerated_mod_string,
)
.unwrap_or_else(|_| panic!(
"Unable to write file {mac_addr_validation_dir}/mod.rs"
));
Ok(())
}