stuffr_cli/lib.rs
1//! Library surface behind the `stuffr` binary.
2//!
3//! Two reasons it exists. [`cli::Cli`] is here so `tests/cli/` can
4//! introspect it through `clap::CommandFactory`: the examples page's test
5//! asserts every flag and subcommand clap knows about is mentioned on the
6//! page, and doing that against the real `Cli` (rather than a hand-copied
7//! list of flag names) keeps the assertion honest as the surface grows.
8//! [`compat`] is here so that `main`, the integration tests and the `compat`
9//! fuzz target all drive the same compatibility families (`bzip2` and
10//! friends) and `install-links`. [`bench`](mod@bench) is here so its
11//! harness, scoring and renderers can be tested with injected times: the CLI
12//! tests run a debug binary, where `stuffr bench` refuses to time anything.
13//! [`format_by_name`] is the `--format`/`--formats` lookup `main` and
14//! `bench` share.
15//!
16//! None of this is a stable API; it is the binary's own code, kept public
17//! for those callers. `bench` and `format_by_name` stay documented, as
18//! `cli`, `compat` and `size` are, rather than `#[doc(hidden)]`: this
19//! crate's docs are the binary's internals docs, and hiding two of its
20//! modules would only make them harder to find.
21
22pub mod bench;
23pub mod cli;
24pub mod compat;
25pub mod size;
26
27/// Resolves a `--format` name against the registry. Shared by
28/// `main`'s verbs and `stuffr bench`.
29///
30/// `FormatId` holds a `&'static str` so the registry can be built from
31/// constants without allocation, but a flag value arrives at runtime as a
32/// `String`. Rather than leak it to reach `'static`, look it up: the registry
33/// already holds the `'static` id, and an unknown name gets a real error
34/// naming what this build does have.
35pub fn format_by_name(name: &str) -> stuffr::Result<stuffr::FormatId> {
36 stuffr::registry()
37 .matrix()
38 .into_iter()
39 .find(|r| r.id.as_str() == name)
40 .map(|r| r.id)
41 .ok_or_else(|| {
42 let known: Vec<&str> = stuffr::registry()
43 .matrix()
44 .iter()
45 .map(|r| r.id.as_str())
46 .collect();
47 stuffr::Error::Usage(format!(
48 "unknown format `{name}`; this build has: {}",
49 if known.is_empty() {
50 "none".to_string()
51 } else {
52 known.join(", ")
53 }
54 ))
55 })
56}