13 releases (4 breaking)
0.5.0 | Nov 4, 2024 |
---|---|
0.4.0 | Nov 3, 2024 |
0.3.2 | Oct 23, 2024 |
0.2.9 | Oct 14, 2024 |
0.1.2 | Oct 13, 2024 |
#470 in Rust patterns
306 downloads per month
24KB
411 lines
fmt-interspersed
This crate provides analogs of the
std::fmt
macros such as
format!
and
write!
to make it easier to
“stringify” the contents of an iterator interspersed with a separator without any
intermediate allocations. The items yielded by the iterator do not need to be the same
type as the separator.
use fmt_interspersed::prelude::*;
let s = "abc";
assert_eq!("a0b0c", format_interspersed!(s.chars(), 0));
Without this crate, the above would look something like the following. (Indeed, the
implementation of format_interspersed!
is nearly identical.)
use std::fmt::Write;
let mut buf = String::new();
let s = "abc";
let sep = 0;
let mut iter = s.chars();
if let Some(c) = iter.next() {
write!(buf, "{c}").unwrap();
for c in iter {
write!(buf, "{sep}").unwrap();
write!(buf, "{c}").unwrap();
}
}
assert_eq!("a0b0c", buf);
In the above, s.chars()::Item
implements
std::fmt::Display
. But you can
specify a custom format to use to display the items, which is useful when the iterator’s
items aren't Display
or need customization. This takes the form of pattern => fmt_args...
as the final argument. (The separator is always stringified using its
Display
implementation and must implement Display
.)
let pairs = vec![("a", 1), ("b", 2)];
assert_eq!(
r#"(x: "a", y: 1); (x: "b", y: 2)"#,
format_interspersed!(pairs, "; ", (x, y) => "(x: {x:?}, y: {y})")
);
There are equivalents of all of the format_args!
-related macros (except for
format_args!
itself), so you can, for example, write to a string, file, or buffer without
allocating any intermediate strings:
// as with `write!`, the necessary trait for writing, either `fmt::Write`
// (for strings) or `io::Write` (for files or other byte sinks), must be in scope
use std::fmt::Write;
let mut buf = String::new();
write_interspersed!(buf, 1_i32..=5, '-', n => "{:02}", n.pow(2))?;
assert_eq!("01-04-09-16-25", buf);
use std::io::{Cursor, Write};
let mut buf = Cursor::new(Vec::<u8>::new());
writeln_interspersed!(buf, "abc".bytes(), ',', b => "{}", b - b'a')?;
write_interspersed!(buf, "abc".bytes(), ',', b => "{}", (b - b'a' + b'A') as char)?;
assert_eq!("0,1,2\nA,B,C", String::from_utf8(buf.into_inner()).unwrap());
Macros, features, and no_std
This crate has two features: alloc
and std
. std
is enabled by default and implies
alloc
. With alloc
and std
disabled, this crate is #![no_std]
-compatible.
Below is the list of this crate’s macros and the features that enable them:
-
Require no features
-
Requires
alloc
-
Require
std
No runtime deps
~0–320KB