Rust format specifier grammar
When several formatting controls appear in one field, their order is fixed. Rust’s standard grammar is the authoritative answer.
format_string := text [ maybe_format text ] *maybe_format := '{' '{' | '}' '}' | formatformat := '{' [ argument ] [ ':' format_spec ] [ ws ] * '}'argument := integer | identifier
format_spec := [[fill]align][sign]['#']['0'][width]['.' precision][type]fill := characteralign := '<' | '^' | '>'sign := '+' | '-'width := countprecision := count | '*'type := '?' | 'x?' | 'X?' | 'o' | 'x' | 'X' | 'p' | 'b' | 'e' | 'E'count := parameter | integerparameter := argument '$'Read a dense specifier left to right
Section titled “Read a dense specifier left to right”Consider {value:#010x}. value selects the argument, : starts the format specification, # requests the alternate hexadecimal form, 0 enables sign-aware numeric zero padding, 10 is the minimum width, and x selects LowerHex.
let value = 27;
assert_eq!(format!("{value:#010x}"), "0x0000001b");The resulting width includes the 0x prefix.
The order is syntax, not style
Section titled “The order is syntax, not style”You cannot arbitrarily rearrange the flags. Fill only has meaning when followed by an alignment operator, the sign comes before # and 0, width comes before precision, and the type suffix comes last.
For normal work, start from the feature you need rather than assembling punctuation from memory. Use arguments and capture, width, alignment, and fill, precision, signs and zero padding, alternate formatting, or formatting traits for the individual pieces.
Use this page as the final lookup when those pieces are combined into one specification.