#formatting #fmt #adapter #traits #offers #recursion #debugging

no-std manyfmt

Easily create more varieties of formatting than the std::fmt traits offer

1 unstable release

0.1.0 Oct 7, 2023

#220 in No standard library

Download history 37/week @ 2023-12-07 50/week @ 2023-12-14 11/week @ 2023-12-21 19/week @ 2023-12-28 9/week @ 2024-01-04 35/week @ 2024-01-11 73/week @ 2024-01-18 26/week @ 2024-01-25 45/week @ 2024-02-01 105/week @ 2024-02-08 108/week @ 2024-02-15 122/week @ 2024-02-22 72/week @ 2024-02-29 32/week @ 2024-03-07 56/week @ 2024-03-14 107/week @ 2024-03-21

283 downloads per month
Used in 7 crates (via all-is-cubes)

MIT/Apache

10KB
76 lines

manyfmt

This Rust library, manyfmt, provides adapters with which you can easily create more varieties of formatting than the std::fmt traits (Display, Debug, Binary, LowerHex, Pointer) offer, without having to write any more boilerplate than absolutely necessary. You can also easily pass additional data down through the formatting recursion.

This library is no_std compatible; it can run anywhere Rust can.

License

Licensed under either of

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.


lib.rs:

Adapters with which you can easily create more varieties of formatting than the std::fmt traits (fmt::Display, fmt::Debug, fmt::Binary, fmt::Pointer, etc.) offer, without having to write any more boilerplate than absolutely necessary. You can also easily pass additional data down through the formatting recursion.

To create a new format, declare a struct (struct MyFormat;) and implement Fmt<MyFormat> for the type you want to be able to format. Then call [Refmt::refmt()] to apply the format as a wrapper type around your data.

Example

The following code implements a minimal, non-validating TOML emitter. This demonstrates how manyfmt can be used to produce complex formatting, that operates within the std::fmt system without allocating, without writing a new by-reference wrapper type for each case.

use std::collections::BTreeMap;
use std::fmt;

use manyfmt::{Fmt, Refmt};

struct TomlFile;
struct TomlTable;

impl<S: AsRef<str>, T: Fmt<TomlTable>> Fmt<TomlFile> for BTreeMap<S, T> {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>, _: &TomlFile) -> fmt::Result {
        for (key, table) in self {
            writeln!(
                fmt,
                "[{key}]\n{table}",
                key = key.as_ref(),
                table = table.refmt(&TomlTable)
            )?;
        }
        Ok(())
    }
}

impl<S: AsRef<str>, T: fmt::Debug> Fmt<TomlTable> for BTreeMap<S, T> {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>, _: &TomlTable) -> fmt::Result {
        for (key, value) in self {
            // A real implementation would use TOML-specific value formatting
            // rather than `Debug`, which promises nothing.
            writeln!(fmt, "{key} = {value:?}", key = key.as_ref())?;
        }
        Ok(())
    }
}

let data = BTreeMap::from([
    ("package", BTreeMap::from([("name", "manyfmt"), ("edition", "2021")])),
    ("lib", BTreeMap::from([("name", "manyfmt")])),
]);

let text = data.refmt(&TomlFile).to_string();

assert_eq!(text,
r#"[lib]
name = "manyfmt"

[package]
edition = "2021"
name = "manyfmt"

"#);

No runtime deps