rtformat
Runtime string formatting for Rust, with std::fmt-compatible placeholder syntax.
Rust's built-in format! macro requires the format string to be a compile-time
literal. rtformat lets you take a template string at runtime — from a config
file, a database, or user input — and format it with the same placeholder syntax
you already know.
Features
{}implicit positional arguments;{0}/{1}explicit indices (reusable)- Types:
{:?}{:#?}{:x}{:X}{:o}{:b}{:e}{:E} - Alignment and fill:
{:<10}{:>10}{:^10}{:_>10} - Sign / radix prefix / zero padding:
{:+}{:#x}{:010} - Width and precision:
{:.3}{:1$}{:.1$}(n$takes the width/precision from argumentn) {{/}}escapes- Custom argument types via
#[derive(FormatArg)] - Fallible formatting (
try_format) and an incremental builder API - Precompiled templates:
Template::parseparses once, formats many times - Output into any
core::fmt::Writesink (write_to/try_write_to) #![no_std]-compatible (requiresalloc)
Not supported: named arguments {name}, pointers {:p}, hexadecimal debug
{x?} / {X?}.
Usage
Add the dependency:
[]
= "0.1"
The rformat! macro
use rformat;
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;
The Format trait
Format is implemented for str (and available on String, Box<str>, etc.
through deref):
use Format;
assert_eq!;
// Fallible variants, for templates that may be invalid:
let result = "{}".try_format;
assert_eq!;
Builder API
Add arguments one at a time:
use Format;
let s = "{} + {} = {2}".builder.arg.arg.arg.build;
assert_eq!;
Precompiled templates
The one-shot APIs parse the template on every call. Template parses once
and formats many times, and can write into any core::fmt::Write sink
(appending, not overwriting):
use Template;
let tpl = parse?;
assert_eq!;
// Reuse with different arguments:
assert_eq!;
// Write into an existing sink:
let mut log = Stringfrom;
tpl.try_write_to?;
assert_eq!;
Syntax errors surface at parse time; argument errors surface at format
time. For a template known at compile time, pair it with LazyLock:
use LazyLock;
use Template;
static TPL: =
new;
assert_eq!;
Custom argument types
Types implementing Display and/or Debug can derive FormatArg. The derive
adapts: {} prefers Display and falls back to Debug, while {:?} / {:#?}
require Debug:
use fmt;
use ;
;
assert_eq!;
For full control over each format type, implement FormatArg manually instead.
Prelude
All commonly used items are available through the prelude:
use *;
assert_eq!;
Notes
- The one-shot APIs (
rformat!,Format::format, ...) parse the template on every call. For a template used repeatedly, parse it once withTemplate::parse(see above). Either way, each format call reuses a single scratch allocation regardless of placeholder count, and thetry_write_tovariants avoid the outputStringas well. rformat!/Format::formattake tuples of up to 16 arguments; for more, or for argument counts only known at runtime, use the builder API.- Output matches
std::fmtsemantics for the supported features; this is guarded by differential tests againststd::format!.
Workspace layout
| Crate | Description |
|---|---|
rtformat |
The formatting engine, traits, and the rformat! macro |
rtformat-derive |
The #[derive(FormatArg)] proc-macro |
License
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.