diff --git a/b3sum/Cargo.lock b/b3sum/Cargo.lock index 212e4924..2ec8f3f7 100644 --- a/b3sum/Cargo.lock +++ b/b3sum/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "anyhow" -version = "1.0.56" +version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27" +checksum = "98161a4e3e2184da77bb14f02184cdd111e83bbbcc9979dfee3c44b9a85f5602" [[package]] name = "arrayref" @@ -73,9 +73,9 @@ dependencies = [ [[package]] name = "block-buffer" -version = "0.10.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" +checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" dependencies = [ "generic-array", ] @@ -94,17 +94,40 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "3.1.6" +version = "4.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8c93436c21e4698bacadf42917db28b23017027a4deccb35dbe47a7e7840123" +checksum = "5840cd9093aabeabf7fd932754c435b7674520fc3ddc935c397837050f0f1e4b" dependencies = [ "atty", "bitflags", - "indexmap", - "os_str_bytes", + "clap_derive", + "clap_lex", + "once_cell", "strsim", "termcolor", - "textwrap", + "terminal_size", +] + +[[package]] +name = "clap_derive" +version = "4.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92289ffc6fb4a85d85c246ddb874c05a87a2e540fb6ad52f7ca07c8c1e1840b1" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8" +dependencies = [ + "os_str_bytes", ] [[package]] @@ -115,9 +138,9 @@ checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" [[package]] name = "crossbeam-channel" -version = "0.5.4" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" +checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" dependencies = [ "cfg-if", "crossbeam-utils", @@ -125,9 +148,9 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" +checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" dependencies = [ "cfg-if", "crossbeam-epoch", @@ -136,33 +159,33 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.8" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c" +checksum = "045ebe27666471bb549370b4b0b3e51b07f56325befa4284db65fc89c02511b1" dependencies = [ "autocfg", "cfg-if", "crossbeam-utils", - "lazy_static", "memoffset", + "once_cell", "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.8" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" +checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc" dependencies = [ "cfg-if", - "lazy_static", + "once_cell", ] [[package]] name = "crypto-common" -version = "0.1.3" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", "typenum", @@ -193,24 +216,45 @@ dependencies = [ [[package]] name = "either" -version = "1.6.1" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" + +[[package]] +name = "errno" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" +dependencies = [ + "errno-dragonfly", + "libc", + "winapi", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] [[package]] name = "fastrand" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" dependencies = [ "instant", ] [[package]] name = "generic-array" -version = "0.14.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" dependencies = [ "typenum", "version_check", @@ -223,10 +267,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" [[package]] -name = "hashbrown" -version = "0.11.2" +name = "heck" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" [[package]] name = "hermit-abi" @@ -243,16 +287,6 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -[[package]] -name = "indexmap" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" -dependencies = [ - "autocfg", - "hashbrown", -] - [[package]] name = "instant" version = "0.1.12" @@ -263,28 +297,28 @@ dependencies = [ ] [[package]] -name = "lazy_static" -version = "1.4.0" +name = "io-lifetimes" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "1ea37f355c05dde75b84bba2d767906ad522e97cd9e2eef2be7a4ab7fb442c06" [[package]] name = "libc" -version = "0.2.121" +version = "0.2.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efaa7b300f3b5fe8eb6bf21ce3895e1751d9665086af2d64b42f19701015ff4f" +checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966" [[package]] -name = "memchr" -version = "2.4.1" +name = "linux-raw-sys" +version = "0.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +checksum = "d4d2456c373231a208ad294c33dc5bff30051eafd954cd4caae83a712b12854d" [[package]] name = "memmap2" -version = "0.5.3" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057a3db23999c867821a7a59feb06a578fcb03685e983dff90daf9e7d24ac08f" +checksum = "95af15f345b17af2efc8ead6080fb8bc376f8cec1b35277b935637595fe77498" dependencies = [ "libc", ] @@ -310,9 +344,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.10.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" +checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0" [[package]] name = "os_pipe" @@ -326,18 +360,57 @@ dependencies = [ [[package]] name = "os_str_bytes" -version = "6.0.0" +version = "6.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff" + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ - "memchr", + "proc-macro2", ] [[package]] name = "rayon" -version = "1.5.1" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90" +checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" dependencies = [ "autocfg", "crossbeam-deque", @@ -347,22 +420,21 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.9.1" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e" +checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" dependencies = [ "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "lazy_static", "num_cpus", ] [[package]] name = "redox_syscall" -version = "0.2.12" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae183fc1b06c149f0c1793e1eb447c8b04bfe46d48e9e48bfb8d2d7ed64ecf0" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ "bitflags", ] @@ -376,6 +448,20 @@ dependencies = [ "winapi", ] +[[package]] +name = "rustix" +version = "0.35.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbb2fda4666def1433b1b05431ab402e42a1084285477222b72d6c564c417cef" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys", +] + [[package]] name = "scopeguard" version = "1.1.0" @@ -404,6 +490,17 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" +[[package]] +name = "syn" +version = "1.0.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "tempfile" version = "3.3.0" @@ -428,10 +525,14 @@ dependencies = [ ] [[package]] -name = "textwrap" -version = "0.15.0" +name = "terminal_size" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" +checksum = "8440c860cf79def6164e4a0a983bcc2305d82419177a0e0c71930d049e3ac5a1" +dependencies = [ + "rustix", + "windows-sys", +] [[package]] name = "typenum" @@ -439,6 +540,12 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" +[[package]] +name = "unicode-ident" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd" + [[package]] name = "version_check" version = "0.9.4" @@ -447,9 +554,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "wild" -version = "2.0.4" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "035793abb854745033f01a07647a79831eba29ec0be377205f2a25b0aa830020" +checksum = "05b116685a6be0c52f5a103334cbff26db643826c7b3735fc0a3ba9871310a74" dependencies = [ "glob", ] @@ -484,3 +591,46 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" + +[[package]] +name = "windows_i686_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" + +[[package]] +name = "windows_i686_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" diff --git a/b3sum/Cargo.toml b/b3sum/Cargo.toml index 3c567b1f..9b43f0a9 100644 --- a/b3sum/Cargo.toml +++ b/b3sum/Cargo.toml @@ -16,7 +16,7 @@ pure = ["blake3/pure"] [dependencies] anyhow = "1.0.25" blake3 = { version = "1", path = "..", features = ["rayon"] } -clap = "3.0.5" +clap = { version = "4.0.8", features = ["derive", "wrap_help"] } hex = "0.4.0" memmap2 = "0.5.3" rayon = "1.2.1" diff --git a/b3sum/README.md b/b3sum/README.md index 0b5e7f93..af10361f 100644 --- a/b3sum/README.md +++ b/b3sum/README.md @@ -5,37 +5,34 @@ A command line utility for calculating Coreutils tools like `b2sum` or `md5sum`. ``` -b3sum 1.3.1 - -USAGE: - b3sum [OPTIONS] [FILE]... - -ARGS: - ... Files to hash, or checkfiles to check. When no file is given, - or when - is given, read standard input. - -OPTIONS: - -c, --check Reads BLAKE3 sums from the [FILE]s and checks them - --derive-key Uses the key derivation mode, with the given - context string. Cannot be used with --keyed. - -h, --help Print help information - --keyed Uses the keyed mode. The secret key is read from standard - input, and it must be exactly 32 raw bytes. - -l, --length The number of output bytes, prior to hex - encoding (default 32) - --no-mmap Disables memory mapping. Currently this also disables - multithreading. - --no-names Omits filenames in the output - --num-threads The maximum number of threads to use. By - default, this is the number of logical cores. - If this flag is omitted, or if its value is 0, - RAYON_NUM_THREADS is also respected. - --quiet Skips printing OK for each successfully verified file. - Must be used with --check. - --raw Writes raw output bytes to stdout, rather than hex. - --no-names is implied. In this case, only a single - input is allowed. - -V, --version Print version information +Usage: b3sum [OPTIONS] [FILE]... + +Arguments: + [FILE]... Files to hash, or checkfiles to check + +Options: + -l, --length + The number of output bytes, prior to hex encoding [default: 32] + --num-threads + The maximum number of threads to use + --keyed + Uses the keyed mode + --derive-key + Uses the key derivation mode, with the given context string + --no-mmap + Disables memory mapping + --no-names + Omits filenames in the output + --raw + Writes raw output bytes to stdout, rather than hex + -c, --check + Reads BLAKE3 sums from the [FILE]s and checks them + --quiet + Skips printing OK for each successfully verified file + -h, --help + Print help information (use `--help` for more detail) + -V, --version + Print version information ``` See also [this document about how the `--check` flag diff --git a/b3sum/src/main.rs b/b3sum/src/main.rs index 0b692a2c..dc0759b0 100644 --- a/b3sum/src/main.rs +++ b/b3sum/src/main.rs @@ -1,5 +1,5 @@ -use anyhow::{bail, ensure, Context, Result}; -use clap::{Arg, Command}; +use anyhow::{bail, ensure, Result}; +use clap::Parser; use std::cmp; use std::convert::TryInto; use std::fs::File; @@ -12,124 +12,109 @@ mod unit_tests; const NAME: &str = "b3sum"; -const FILE_ARG: &str = "FILE"; -const DERIVE_KEY_ARG: &str = "derive-key"; +const DERIVE_KEY_ARG: &str = "derive_key"; const KEYED_ARG: &str = "keyed"; const LENGTH_ARG: &str = "length"; -const NO_MMAP_ARG: &str = "no-mmap"; -const NO_NAMES_ARG: &str = "no-names"; -const NUM_THREADS_ARG: &str = "num-threads"; +const NO_NAMES_ARG: &str = "no_names"; const RAW_ARG: &str = "raw"; const CHECK_ARG: &str = "check"; -const QUIET_ARG: &str = "quiet"; + +#[derive(Parser)] +#[command(version, max_term_width(80))] +struct Inner { + /// Files to hash, or checkfiles to check. + /// + /// When no file is given, or when - is given, read standard input. + file: Vec, + + /// The number of output bytes, prior to hex encoding. + #[arg( + short, + long, + default_value_t = blake3::OUT_LEN as u64, + value_name("LEN") + )] + length: u64, + + /// The maximum number of threads to use. + /// + /// By default, this is the number of logical cores. If this flag is + /// omitted, or if its value is 0, RAYON_NUM_THREADS is also respected. + #[arg(long, value_name("NUM"))] + num_threads: Option, + + /// Uses the keyed mode. + /// + /// The secret key is read from standard input, and it must be exactly 32 + /// raw bytes. + #[arg(long, requires("file"))] + keyed: bool, + + /// Uses the key derivation mode, with the given context string. + /// + /// Cannot be used with --keyed. + #[arg(long, value_name("CONTEXT"), conflicts_with(KEYED_ARG))] + derive_key: Option, + + /// Disables memory mapping. + /// + /// Currently this also disables multithreading. + #[arg(long)] + no_mmap: bool, + + /// Omits filenames in the output. + #[arg(long)] + no_names: bool, + + /// Writes raw output bytes to stdout, rather than hex. + /// + /// --no-names is implied. In this case, only a single input is allowed. + #[arg(long)] + raw: bool, + + /// Reads BLAKE3 sums from the [FILE]s and checks them. + #[arg( + short, + long, + conflicts_with(DERIVE_KEY_ARG), + conflicts_with(KEYED_ARG), + conflicts_with(LENGTH_ARG), + conflicts_with(RAW_ARG), + conflicts_with(NO_NAMES_ARG) + )] + check: bool, + + /// Skips printing OK for each successfully verified file. + /// + /// Must be used with --check. + #[arg(long, requires(CHECK_ARG))] + quiet: bool, +} struct Args { - inner: clap::ArgMatches, + inner: Inner, file_args: Vec, base_hasher: blake3::Hasher, } impl Args { fn parse() -> Result { - let inner = Command::new(NAME) - .version(env!("CARGO_PKG_VERSION")) - .arg( - Arg::new(FILE_ARG) - .multiple_occurrences(true) - .allow_invalid_utf8(true) - .help( - "Files to hash, or checkfiles to check. When no file is given,\n\ - or when - is given, read standard input.", - ), - ) - .arg( - Arg::new(LENGTH_ARG) - .long(LENGTH_ARG) - .short('l') - .takes_value(true) - .value_name("LEN") - .help( - "The number of output bytes, prior to hex\n\ - encoding (default 32)", - ), - ) - .arg( - Arg::new(NUM_THREADS_ARG) - .long(NUM_THREADS_ARG) - .takes_value(true) - .value_name("NUM") - .help( - "The maximum number of threads to use. By\n\ - default, this is the number of logical cores.\n\ - If this flag is omitted, or if its value is 0,\n\ - RAYON_NUM_THREADS is also respected.", - ), - ) - .arg(Arg::new(KEYED_ARG).long(KEYED_ARG).requires(FILE_ARG).help( - "Uses the keyed mode. The secret key is read from standard\n\ - input, and it must be exactly 32 raw bytes.", - )) - .arg( - Arg::new(DERIVE_KEY_ARG) - .long(DERIVE_KEY_ARG) - .conflicts_with(KEYED_ARG) - .takes_value(true) - .value_name("CONTEXT") - .help( - "Uses the key derivation mode, with the given\n\ - context string. Cannot be used with --keyed.", - ), - ) - .arg(Arg::new(NO_MMAP_ARG).long(NO_MMAP_ARG).help( - "Disables memory mapping. Currently this also disables\n\ - multithreading.", - )) - .arg( - Arg::new(NO_NAMES_ARG) - .long(NO_NAMES_ARG) - .help("Omits filenames in the output"), - ) - .arg(Arg::new(RAW_ARG).long(RAW_ARG).help( - "Writes raw output bytes to stdout, rather than hex.\n\ - --no-names is implied. In this case, only a single\n\ - input is allowed.", - )) - .arg( - Arg::new(CHECK_ARG) - .long(CHECK_ARG) - .short('c') - .conflicts_with(DERIVE_KEY_ARG) - .conflicts_with(KEYED_ARG) - .conflicts_with(LENGTH_ARG) - .conflicts_with(RAW_ARG) - .conflicts_with(NO_NAMES_ARG) - .help("Reads BLAKE3 sums from the [FILE]s and checks them"), - ) - .arg( - Arg::new(QUIET_ARG) - .long(QUIET_ARG) - .requires(CHECK_ARG) - .help( - "Skips printing OK for each successfully verified file.\n\ - Must be used with --check.", - ), - ) - // wild::args_os() is equivalent to std::env::args_os() on Unix, - // but on Windows it adds support for globbing. - .get_matches_from(wild::args_os()); - let file_args = if let Some(iter) = inner.values_of_os(FILE_ARG) { - iter.map(|s| s.into()).collect() + // wild::args_os() is equivalent to std::env::args_os() on Unix, + // but on Windows it adds support for globbing. + let inner = Inner::parse_from(wild::args_os()); + let file_args = if !inner.file.is_empty() { + inner.file.clone() } else { vec!["-".into()] }; - if inner.is_present(RAW_ARG) && file_args.len() > 1 { + if inner.raw && file_args.len() > 1 { bail!("Only one filename can be provided when using --raw"); } - let base_hasher = if inner.is_present(KEYED_ARG) { + let base_hasher = if inner.keyed { // In keyed mode, since stdin is used for the key, we can't handle // `-` arguments. Input::open handles that case below. blake3::Hasher::new_keyed(&read_key_from_stdin()?) - } else if let Some(context) = inner.value_of(DERIVE_KEY_ARG) { + } else if let Some(ref context) = inner.derive_key { blake3::Hasher::new_derive_key(context) } else { blake3::Hasher::new() @@ -141,48 +126,36 @@ impl Args { }) } - fn num_threads(&self) -> Result> { - if let Some(num_threads_str) = self.inner.value_of(NUM_THREADS_ARG) { - Ok(Some( - num_threads_str - .parse() - .context("Failed to parse num threads.")?, - )) - } else { - Ok(None) - } + fn num_threads(&self) -> Option { + self.inner.num_threads } fn check(&self) -> bool { - self.inner.is_present(CHECK_ARG) + self.inner.check } fn raw(&self) -> bool { - self.inner.is_present(RAW_ARG) + self.inner.raw } fn no_mmap(&self) -> bool { - self.inner.is_present(NO_MMAP_ARG) + self.inner.no_mmap } fn no_names(&self) -> bool { - self.inner.is_present(NO_NAMES_ARG) + self.inner.no_names } - fn len(&self) -> Result { - if let Some(length) = self.inner.value_of(LENGTH_ARG) { - length.parse::().context("Failed to parse length.") - } else { - Ok(blake3::OUT_LEN as u64) - } + fn len(&self) -> u64 { + self.inner.length } fn keyed(&self) -> bool { - self.inner.is_present(KEYED_ARG) + self.inner.keyed } fn quiet(&self) -> bool { - self.inner.is_present(QUIET_ARG) + self.inner.quiet } } @@ -307,7 +280,7 @@ fn maybe_memmap_file(file: &File) -> Result> { fn write_hex_output(mut output: blake3::OutputReader, args: &Args) -> Result<()> { // Encoding multiples of the block size is most efficient. - let mut len = args.len()?; + let mut len = args.len(); let mut block = [0; blake3::guts::BLOCK_LEN]; while len > 0 { output.fill(&mut block); @@ -320,7 +293,7 @@ fn write_hex_output(mut output: blake3::OutputReader, args: &Args) -> Result<()> } fn write_raw_output(output: blake3::OutputReader, args: &Args) -> Result<()> { - let mut output = output.take(args.len()?); + let mut output = output.take(args.len()); let stdout = std::io::stdout(); let mut handler = stdout.lock(); std::io::copy(&mut output, &mut handler)?; @@ -589,7 +562,7 @@ fn check_one_checkfile(path: &Path, args: &Args, some_file_failed: &mut bool) -> fn main() -> Result<()> { let args = Args::parse()?; let mut thread_pool_builder = rayon::ThreadPoolBuilder::new(); - if let Some(num_threads) = args.num_threads()? { + if let Some(num_threads) = args.num_threads() { thread_pool_builder = thread_pool_builder.num_threads(num_threads); } let thread_pool = thread_pool_builder.build()?; @@ -619,3 +592,13 @@ fn main() -> Result<()> { std::process::exit(if some_file_failed { 1 } else { 0 }); }) } + +#[cfg(test)] +mod test { + use clap::CommandFactory; + + #[test] + fn test_args() { + crate::Inner::command().debug_assert(); + } +}