Expand description
The pw_format crate provides format string parsing and formatting utilities to:
- Parse and syntax-check format strings (
printfandcore::fmt). - Understand format string argument types at compile time in proc macros.
- Format dynamic values according to format strings at runtime.
pw_format is written against std and is not intended to be
used in an embedded on-device context. Some efficiency and memory is traded for a
more expressive interface that exposes the format string’s syntax tree
to the API client.
§Proc Macros
The macros module provides infrastructure for implementing proc macros
that take format strings as arguments.
§Parsing Example
use pw_format::{
Alignment, Argument, ConversionSpec, Flag, FormatFragment, FormatString,
Length, MinFieldWidth, Precision, Primitive, Style,
};
let format_string =
FormatString::parse_printf("long double %+ 4.2Lf is %-03hd%%.").unwrap();
assert_eq!(format_string, FormatString {
fragments: vec![
FormatFragment::Literal("long double ".to_string()),
FormatFragment::Conversion(ConversionSpec {
argument: Argument::None,
fill: ' ',
alignment: Alignment::None,
flags: [Flag::ForceSign, Flag::SpaceSign].into_iter().collect(),
min_field_width: MinFieldWidth::Fixed(4),
precision: Precision::Fixed(2),
length: Some(Length::LongDouble),
primitive: Primitive::Float,
style: Style::None,
}),
FormatFragment::Literal(" is ".to_string()),
FormatFragment::Conversion(ConversionSpec {
argument: Argument::None,
fill: ' ',
alignment: Alignment::Left,
flags: [Flag::LeftJustify, Flag::LeadingZeros]
.into_iter()
.collect(),
min_field_width: MinFieldWidth::Fixed(3),
precision: Precision::None,
length: Some(Length::Short),
primitive: Primitive::Integer,
style: Style::None,
}),
FormatFragment::Literal("%.".to_string()),
]
});§Runtime Formatting Example
use pw_format::{Arg, FormatString, FormatStyle};
let fmt = FormatString::parse_printf("Hello %s, code: 0x%04x!").unwrap();
let output = fmt.format(
&[Arg::Str("world".to_string()), Arg::Uint(42)],
FormatStyle::Printf,
);
assert_eq!(output, "Hello world, code: 0x002a!");§Error Formatting Example
When formatting strings with missing or mismatched arguments, custom error formatters
implementing FormatError can be supplied:
use pw_format::{Arg, ConversionSpec, FormatError, FormatString, FormatStyle};
struct MyErrorFormatter;
impl FormatError for MyErrorFormatter {
type Error = ();
fn format_error(&self, spec: &ConversionSpec, _error: &()) -> String {
format!("<[{} ERROR]>", spec.to_printf())
}
fn format_missing(&self, spec: &ConversionSpec) -> String {
format!("<[{} MISSING]>", spec.to_printf())
}
fn format_type_error(&self, spec: &ConversionSpec, _arg: &Arg) -> String {
format!("<[{} TYPE_ERROR]>", spec.to_printf())
}
}
let fmt = FormatString::parse_printf("Value: %d").unwrap();
let output = fmt.format_with_errors(&[], FormatStyle::Printf, &MyErrorFormatter);
assert_eq!(output, "Value: <[%d MISSING]>");Structs§
- Conversion
Spec - A printf conversion specification aka a % clause.
- Format
String - A parsed format string.
Enums§
- Alignment
- A core::fmt alignment spec.
- Arg
- Representation of a decoded argument.
- Argument
- An argument in a core::fmt style alignment spec.
- Flag
- A printf flag (the ‘+’ in %+d).
- Format
Fragment - A fragment of a printf format string.
- Format
Style - The style of formatting to apply (influences defaults).
- Length
- A printf length (the l in %ld).
- MinField
Width - A printf minimum field width (the 5 in %5d).
- Precision
- A printf precision (the .5 in %.5d).
- Primitive
- Primitive type of a conversion (integer, float, string, etc.)
- Style
- The abstract formatting style for a conversion.
Traits§
- Format
Error - A trait for formatting conversion specifiers that failed, were skipped, or were missing.