mirror of
https://github.com/uutils/coreutils
synced 2024-12-12 14:22:41 +00:00
Use a PHF map for util_map()
Rather than building a HashMap at compile time, use the phf (and phf_codegen) crate to build the map at compile time in build.rs
This commit is contained in:
parent
57dc11e586
commit
bb41f4ffe5
5 changed files with 96 additions and 81 deletions
46
Cargo.lock
generated
46
Cargo.lock
generated
|
@ -302,6 +302,8 @@ dependencies = [
|
|||
"lazy_static",
|
||||
"libc",
|
||||
"nix 0.23.1",
|
||||
"phf",
|
||||
"phf_codegen",
|
||||
"pretty_assertions",
|
||||
"rand",
|
||||
"regex",
|
||||
|
@ -1347,6 +1349,44 @@ version = "0.1.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
|
||||
|
||||
[[package]]
|
||||
name = "phf"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259"
|
||||
dependencies = [
|
||||
"phf_shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_codegen"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd"
|
||||
dependencies = [
|
||||
"phf_generator",
|
||||
"phf_shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_generator"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6"
|
||||
dependencies = [
|
||||
"phf_shared",
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_shared"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096"
|
||||
dependencies = [
|
||||
"siphasher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.24"
|
||||
|
@ -1758,6 +1798,12 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a86232ab60fa71287d7f2ddae4a7073f6b7aac33631c3015abb556f08c6d0a3e"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.8.0"
|
||||
|
|
|
@ -247,6 +247,7 @@ test = [ "uu_test" ]
|
|||
[dependencies]
|
||||
clap = { version = "3.0", features = ["wrap_help", "cargo"] }
|
||||
clap_complete = "3.0"
|
||||
phf = "0.10.1"
|
||||
lazy_static = { version="1.3" }
|
||||
textwrap = { version="0.14", features=["terminal_size"] }
|
||||
uucore = { version=">=0.0.11", package="uucore", path="src/uucore" }
|
||||
|
@ -387,6 +388,9 @@ nix = "0.23.1"
|
|||
rust-users = { version="0.10", package="users" }
|
||||
unix_socket = "0.5.0"
|
||||
|
||||
[build-dependencies]
|
||||
phf_codegen = "0.10.0"
|
||||
|
||||
[[bin]]
|
||||
name = "coreutils"
|
||||
path = "src/bin/coreutils.rs"
|
||||
|
|
121
build.rs
121
build.rs
|
@ -12,9 +12,9 @@ pub fn main() {
|
|||
println!("cargo:rustc-cfg=build={:?}", profile);
|
||||
}
|
||||
|
||||
let env_feature_prefix: &str = "CARGO_FEATURE_";
|
||||
let feature_prefix: &str = "feat_";
|
||||
let override_prefix: &str = "uu_";
|
||||
const ENV_FEATURE_PREFIX: &str = "CARGO_FEATURE_";
|
||||
const FEATURE_PREFIX: &str = "feat_";
|
||||
const OVERRIDE_PREFIX: &str = "uu_";
|
||||
|
||||
let out_dir = env::var("OUT_DIR").unwrap();
|
||||
// println!("cargo:warning=out_dir={}", out_dir);
|
||||
|
@ -25,16 +25,16 @@ pub fn main() {
|
|||
|
||||
let mut crates = Vec::new();
|
||||
for (key, val) in env::vars() {
|
||||
if val == "1" && key.starts_with(env_feature_prefix) {
|
||||
let krate = key[env_feature_prefix.len()..].to_lowercase();
|
||||
if val == "1" && key.starts_with(ENV_FEATURE_PREFIX) {
|
||||
let krate = key[ENV_FEATURE_PREFIX.len()..].to_lowercase();
|
||||
match krate.as_ref() {
|
||||
"default" | "macos" | "unix" | "windows" | "selinux" => continue, // common/standard feature names
|
||||
"nightly" | "test_unimplemented" => continue, // crate-local custom features
|
||||
"test" => continue, // over-ridden with 'uu_test' to avoid collision with rust core crate 'test'
|
||||
s if s.starts_with(feature_prefix) => continue, // crate feature sets
|
||||
s if s.starts_with(FEATURE_PREFIX) => continue, // crate feature sets
|
||||
_ => {} // util feature name
|
||||
}
|
||||
crates.push(krate.to_string());
|
||||
crates.push(krate);
|
||||
}
|
||||
}
|
||||
crates.sort();
|
||||
|
@ -43,33 +43,23 @@ pub fn main() {
|
|||
let mut tf = File::create(Path::new(&out_dir).join("test_modules.rs")).unwrap();
|
||||
|
||||
mf.write_all(
|
||||
"type UtilityMap<T> = HashMap<&'static str, (fn(T) -> i32, fn() -> App<'static>)>;\n\
|
||||
"type UtilityMap<T> = phf::Map<&'static str, (fn(T) -> i32, fn() -> App<'static>)>;\n\
|
||||
\n\
|
||||
fn util_map<T: uucore::Args>() -> UtilityMap<T> {\n\
|
||||
\t#[allow(unused_mut)]\n\
|
||||
\t#[allow(clippy::let_and_return)]\n\
|
||||
\tlet mut map = UtilityMap::new();\n\
|
||||
"
|
||||
.as_bytes(),
|
||||
fn util_map<T: uucore::Args>() -> UtilityMap<T> {\n"
|
||||
.as_bytes(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut phf_map = phf_codegen::Map::<String>::new();
|
||||
for krate in crates {
|
||||
let map_value = format!("({krate}::uumain, {krate}::uu_app)", krate = krate);
|
||||
match krate.as_ref() {
|
||||
// 'test' is named uu_test to avoid collision with rust core crate 'test'.
|
||||
// It can also be invoked by name '[' for the '[ expr ] syntax'.
|
||||
"uu_test" => {
|
||||
mf.write_all(
|
||||
format!(
|
||||
"\
|
||||
\tmap.insert(\"test\", ({krate}::uumain, {krate}::uu_app));\n\
|
||||
\t\tmap.insert(\"[\", ({krate}::uumain, {krate}::uu_app));\n\
|
||||
",
|
||||
krate = krate
|
||||
)
|
||||
.as_bytes(),
|
||||
)
|
||||
.unwrap();
|
||||
phf_map.entry(String::from("test"), &map_value);
|
||||
phf_map.entry(String::from("["), &map_value);
|
||||
|
||||
tf.write_all(
|
||||
format!(
|
||||
"#[path=\"{dir}/test_test.rs\"]\nmod test_test;\n",
|
||||
|
@ -79,20 +69,12 @@ pub fn main() {
|
|||
)
|
||||
.unwrap()
|
||||
}
|
||||
k if k.starts_with(override_prefix) => {
|
||||
mf.write_all(
|
||||
format!(
|
||||
"\tmap.insert(\"{k}\", ({krate}::uumain, {krate}::uu_app));\n",
|
||||
k = &krate[override_prefix.len()..],
|
||||
krate = krate
|
||||
)
|
||||
.as_bytes(),
|
||||
)
|
||||
.unwrap();
|
||||
k if k.starts_with(OVERRIDE_PREFIX) => {
|
||||
phf_map.entry(String::from(&krate[OVERRIDE_PREFIX.len()..]), &map_value);
|
||||
tf.write_all(
|
||||
format!(
|
||||
"#[path=\"{dir}/test_{k}.rs\"]\nmod test_{k};\n",
|
||||
k = &krate[override_prefix.len()..],
|
||||
k = &krate[OVERRIDE_PREFIX.len()..],
|
||||
dir = util_tests_dir,
|
||||
)
|
||||
.as_bytes(),
|
||||
|
@ -100,14 +82,10 @@ pub fn main() {
|
|||
.unwrap()
|
||||
}
|
||||
"false" | "true" => {
|
||||
mf.write_all(
|
||||
format!(
|
||||
"\tmap.insert(\"{krate}\", (r#{krate}::uumain, r#{krate}::uu_app));\n",
|
||||
krate = krate
|
||||
)
|
||||
.as_bytes(),
|
||||
)
|
||||
.unwrap();
|
||||
phf_map.entry(
|
||||
String::from(&krate),
|
||||
&format!("(r#{krate}::uumain, r#{krate}::uu_app)", krate = krate),
|
||||
);
|
||||
tf.write_all(
|
||||
format!(
|
||||
"#[path=\"{dir}/test_{krate}.rs\"]\nmod test_{krate};\n",
|
||||
|
@ -119,29 +97,25 @@ pub fn main() {
|
|||
.unwrap()
|
||||
}
|
||||
"hashsum" => {
|
||||
mf.write_all(
|
||||
format!(
|
||||
"\
|
||||
\tmap.insert(\"{krate}\", ({krate}::uumain, {krate}::uu_app_custom));\n\
|
||||
\t\tmap.insert(\"md5sum\", ({krate}::uumain, {krate}::uu_app_common));\n\
|
||||
\t\tmap.insert(\"sha1sum\", ({krate}::uumain, {krate}::uu_app_common));\n\
|
||||
\t\tmap.insert(\"sha224sum\", ({krate}::uumain, {krate}::uu_app_common));\n\
|
||||
\t\tmap.insert(\"sha256sum\", ({krate}::uumain, {krate}::uu_app_common));\n\
|
||||
\t\tmap.insert(\"sha384sum\", ({krate}::uumain, {krate}::uu_app_common));\n\
|
||||
\t\tmap.insert(\"sha512sum\", ({krate}::uumain, {krate}::uu_app_common));\n\
|
||||
\t\tmap.insert(\"sha3sum\", ({krate}::uumain, {krate}::uu_app_common));\n\
|
||||
\t\tmap.insert(\"sha3-224sum\", ({krate}::uumain, {krate}::uu_app_common));\n\
|
||||
\t\tmap.insert(\"sha3-256sum\", ({krate}::uumain, {krate}::uu_app_common));\n\
|
||||
\t\tmap.insert(\"sha3-384sum\", ({krate}::uumain, {krate}::uu_app_common));\n\
|
||||
\t\tmap.insert(\"sha3-512sum\", ({krate}::uumain, {krate}::uu_app_common));\n\
|
||||
\t\tmap.insert(\"shake128sum\", ({krate}::uumain, {krate}::uu_app_common));\n\
|
||||
\t\tmap.insert(\"shake256sum\", ({krate}::uumain, {krate}::uu_app_common));\n\
|
||||
",
|
||||
krate = krate
|
||||
)
|
||||
.as_bytes(),
|
||||
)
|
||||
.unwrap();
|
||||
phf_map.entry(
|
||||
String::from(&krate),
|
||||
&format!("({krate}::uumain, {krate}::uu_app_custom)", krate = krate),
|
||||
);
|
||||
|
||||
let map_value = format!("({krate}::uumain, {krate}::uu_app_common)", krate = krate);
|
||||
phf_map.entry(String::from("md5sum"), &map_value);
|
||||
phf_map.entry(String::from("sha1sum"), &map_value);
|
||||
phf_map.entry(String::from("sha224sum"), &map_value);
|
||||
phf_map.entry(String::from("sha256sum"), &map_value);
|
||||
phf_map.entry(String::from("sha384sum"), &map_value);
|
||||
phf_map.entry(String::from("sha512sum"), &map_value);
|
||||
phf_map.entry(String::from("sha3sum"), &map_value);
|
||||
phf_map.entry(String::from("sha3-224sum"), &map_value);
|
||||
phf_map.entry(String::from("sha3-256sum"), &map_value);
|
||||
phf_map.entry(String::from("sha3-384sum"), &map_value);
|
||||
phf_map.entry(String::from("sha3-512sum"), &map_value);
|
||||
phf_map.entry(String::from("shake128sum"), &map_value);
|
||||
phf_map.entry(String::from("shake256sum"), &map_value);
|
||||
tf.write_all(
|
||||
format!(
|
||||
"#[path=\"{dir}/test_{krate}.rs\"]\nmod test_{krate};\n",
|
||||
|
@ -153,14 +127,7 @@ pub fn main() {
|
|||
.unwrap()
|
||||
}
|
||||
_ => {
|
||||
mf.write_all(
|
||||
format!(
|
||||
"\tmap.insert(\"{krate}\", ({krate}::uumain, {krate}::uu_app));\n",
|
||||
krate = krate
|
||||
)
|
||||
.as_bytes(),
|
||||
)
|
||||
.unwrap();
|
||||
phf_map.entry(String::from(&krate), &map_value);
|
||||
tf.write_all(
|
||||
format!(
|
||||
"#[path=\"{dir}/test_{krate}.rs\"]\nmod test_{krate};\n",
|
||||
|
@ -173,8 +140,8 @@ pub fn main() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
mf.write_all(b"map\n}\n").unwrap();
|
||||
write!(mf, "{}", phf_map.build()).unwrap();
|
||||
mf.write_all(b"\n}\n").unwrap();
|
||||
|
||||
mf.flush().unwrap();
|
||||
tf.flush().unwrap();
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
use clap::{App, Arg};
|
||||
use clap_complete::Shell;
|
||||
use std::cmp;
|
||||
use std::collections::hash_map::HashMap;
|
||||
use std::ffi::OsStr;
|
||||
use std::ffi::OsString;
|
||||
use std::io::{self, Write};
|
||||
|
@ -171,7 +170,7 @@ fn gen_completions<T: uucore::Args>(
|
|||
|
||||
fn gen_coreutils_app<T: uucore::Args>(util_map: UtilityMap<T>) -> App<'static> {
|
||||
let mut app = App::new("coreutils");
|
||||
for (_, (_, sub_app)) in util_map {
|
||||
for (_, (_, sub_app)) in &util_map {
|
||||
app = app.subcommand(sub_app());
|
||||
}
|
||||
app
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
// file that was distributed with this source code.
|
||||
|
||||
use clap::App;
|
||||
use std::collections::hash_map::HashMap;
|
||||
use std::ffi::OsString;
|
||||
use std::fs::File;
|
||||
use std::io::{self, Write};
|
||||
|
@ -32,7 +31,7 @@ fn main() -> io::Result<()> {
|
|||
* [Multi-call binary](multicall.md)\n",
|
||||
);
|
||||
|
||||
let mut utils = utils.iter().collect::<Vec<_>>();
|
||||
let mut utils = utils.entries().collect::<Vec<_>>();
|
||||
utils.sort();
|
||||
for (&name, (_, app)) in utils {
|
||||
if name == "[" {
|
||||
|
|
Loading…
Reference in a new issue