1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
//! Runtime string formatting with `std::fmt`-compatible placeholder syntax.
//!
//! - `{}` 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 argument `n`)
//! - `{{` / `}}` escapes
//! - Format into any `core::fmt::Write` sink; precompiled templates via [`Template`]
//!
//! Not supported: named arguments `{name}`, pointers `{:p}`, hexadecimal debug `{x?}` / `{X?}`.
//!
//! This crate is `#![no_std]`-compatible and requires `alloc`.
//!
//! # 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 core::fmt;
//! use rtformat::{rformat, Format, FormatArg};
//!
//! #[derive(Debug, FormatArg)]
//! struct Color(u8, u8, u8);
//!
//! impl fmt::Display for Color {
//! fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
//! write!(f, "#{:02x}{:02x}{:02x}", self.0, self.1, self.2)
//! }
//! }
//!
//! assert_eq!(rformat!("{}", Color(255, 128, 0)), "#ff8000");
//! ```
//!
//! For full control over each format type, implement [`FormatArg`] manually
//! instead.
//!
//! # Examples
//!
//! ```
//! use rtformat::{rformat, Format};
//!
//! assert_eq!(rformat!("Hello {}!", "world"), "Hello world!");
//! assert_eq!("{} + {} = {2}".format(&(1, 2, 3)), "1 + 2 = 3");
//! assert_eq!(rformat!("{:#010x}", 255), "0x000000ff");
//! ```
//!
//! # Builder API
//!
//! Templates can also be formatted incrementally with
//! [`FormatBuilder`], adding one argument per call:
//!
//! ```
//! use rtformat::Format;
//!
//! let s = "{} + {} = {2}".builder().arg(&1).arg(&2).arg(&3).build();
//! assert_eq!(s, "1 + 2 = 3");
//! ```
//!
//! # Precompiled templates
//!
//! The one-shot APIs parse the template on every call. [`Template`] parses
//! once, formats many times, and can also write into any
//! [`core::fmt::Write`] sink (appending, not overwriting):
//!
//! ```
//! use rtformat::Template;
//!
//! let tpl = Template::parse("{} + {} = {2}")?;
//! assert_eq!(tpl.format(&(1, 2, 3)), "1 + 2 = 3");
//!
//! let mut log = String::from("log: ");
//! tpl.try_write_to(&mut log, &(1, 2, 3))?;
//! assert_eq!(log, "log: 1 + 2 = 3");
//! # Ok::<(), rtformat::FormatError>(())
//! ```
//!
//! All commonly used items are also available through [`prelude`]:
//!
//! ```
//! use rtformat::prelude::*;
//!
//! assert_eq!(rformat!("Hello {}!", "world"), "Hello world!");
//! ```
extern crate alloc;
extern crate std;
extern crate self as rtformat;
pub use ;
pub use ;
pub use FormatError;
pub use Format;
pub use FormatParam;
pub use Template;
pub use FormatArg;
/// Formats arguments into a template string at runtime.
///
/// Convenience wrapper around [`Format::format`]: packs the arguments into a
/// tuple and calls `format`.
///
/// # Panics
///
/// Panics if the template or the arguments are invalid. Use
/// [`Format::try_format`] if failure is possible.
///
/// # Examples
///
/// ```
/// use rtformat::{rformat, Format};
///
/// assert_eq!(rformat!("{0} + {1} = {2}", 1, 2, 3), "1 + 2 = 3");
/// assert_eq!(rformat!("{:.2}", 3.14159), "3.14");
/// ```