A zero-allocation argv parser for usage specs.
This crate implements the binding rules of the argv grammar: which token becomes which flag or argument, when a word selects a subcommand, and what is an error. It does so without building a command tree, without allocating, and in one pass.
It is the runtime half of a compiled parser. The tables it reads are meant to
be emitted by a derive macro as static data, so that starting a parse costs
nothing at all: there is no construction step to pay for, only the walk over
argv.
Shape of the API
Parsing yields [Event]s rather than a map. A map would have to allocate,
and would then have to be read back out again — whereas generated code can
assign an event straight into a struct field. This is the same reason serde
deserializes into your type instead of into a Value.
use ;
static FORCE: Flag = Flag ;
static FILE: Arg = Arg ;
static ROOT: Command = Command ;
let argv = .map;
let mut parser = new;
let mut force = false;
let mut file = None;
while let Some = parser.next_event
assert!;
assert_eq!;
Values are bytes
An [Event] carries &[u8], borrowed from argv. Converting to &str is
the caller's step ([as_str]), and it is the right place for the only
failure a value can have: a command line that is not valid UTF-8 still
parses — flags match, subcommands route — and only the values that are
actually looked at can fail to convert.
Slicing an OsStr into &str pieces safely is not possible without
allocating or unsafe, and this crate forbids unsafe. Bytes are what is
left, and they turn out to be the honest interface anyway.
What this crate does not do
Only binding. Required-ness, choices, env fallback, defaults, var_min
and var_max are all decided after the last token is read, and they need to
know a value's type, so they belong to the layer that owns the target struct.
Keeping them out is what makes this loop small.