Give user abilities to write custom adapters over `std::fmt::Formatter`

Currently, I can't find a way to implement nested indentation with Formatter. The standard library's DebugMap and DebugStruct does so via an internal PadAdapter, which you can't implement yourself because it touches private fields of Formatter. I think the standard library should add a way that allows users to write adapters like PadAdapter, either by simply making wrap_buf public or by some other mechanisms.

4 Likes

It's new to me that this is not possible, because we are doing this in diesel since some time.

1 Like

Diesel only implements the part of PadAdapter that is responsible for indentation. This is sufficient in this case.

However, Debug* structures essentially clone a Formatter while substituting a Write implementation. For instance, consider the following program:

#[derive(Debug)]
struct Hi {
    field: i32,
}

fn main() {
    println!("{:_>#10?}", Hi { field: 33 })
}

Outputs:

Hi {
    field: ________33,
}

In this case, the width parameter of a formatter is passed through.

Just as @xfix said, an implementation like diesel's contains only the methods provided by fmt::Write trait, whereas std's implementation basically swaps out the underlying buffer (a trait object of fmt::Write) with a custom trait object. This way, not only that the interface of Formatter is preserved, any calls to any methods on Formatter will go through your custom trait object.

I'm not sure this is what you need but I wrote indentation for anyhow and extracted it into a crate here https://docs.rs/indenter/0.1.3/indenter/ where you wrap a formatter with another object that impls fmt::Write and it handles detecting newlines and inserting the indentation after each newline.

The specific implementation is only really setup to handle the one tier of indentation needed by when running Display::fmt on an error but it might be possible to extend it to fit your needs, and I'd be happy to add features you need back to the library to make it more generally useful.