Linus Dikomey
Linus Dikomey

Reputation: 114

Apply format arguments to struct members in Display implementation

I want to apply format arguments (for example to limit the amount of digits) to the members of my struct. My current implementation looks roughly like this:

use std::fmt;

#[derive(Debug)]
pub struct Vec2 { x: f32, y: f32 }
impl fmt::Display for Vec2 {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "[{}, {}]", self.x, self.y)
    }
}

If I use the automatically derived debug printing using e.g. {:.2?}, the arguments are applied and only 2 places after the decimal are printed. This doesn't seem to work with my Display implementation though using {:.2}. I tried to look at the Debug implementation using cargo expand but there are many functions specifically for Debug.

Upvotes: 1

Views: 709

Answers (1)

Chayim Friedman
Chayim Friedman

Reputation: 70990

The easiest way will be to forward the formatting:

impl fmt::Display for Vec2 {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str("[")?;
        fmt::Display::fmt(&self.x, f)?;
        f.write_str(", ")?;
        fmt::Display::fmt(&self.y, f)?;
        f.write_str("]")
    }
}

Note that if you want to have all formatting specifiers, you have to implement additional traits. For floats, it's only std::fmt::LowerExp and std::fmt::UpperExp. You can make a little helper function to not duplicate code:

impl Vec2 {
    fn fmt(
        &self,
        f: &mut fmt::Formatter<'_>,
        fmt_fn: fn(&f32, f: &mut fmt::Formatter<'_>) -> fmt::Result,
    ) -> fmt::Result {
        f.write_str("[")?;
        fmt_fn(&self.x, f)?;
        f.write_str(", ")?;
        fmt_fn(&self.y, f)?;
        f.write_str("]")
    }
}
impl fmt::Display for Vec2 {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.fmt(f, fmt::Display::fmt)
    }
}
impl fmt::LowerExp for Vec2 {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.fmt(f, fmt::LowerExp::fmt)
    }
}
impl fmt::UpperExp for Vec2 {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.fmt(f, fmt::UpperExp::fmt)
    }
}

Upvotes: 1

Related Questions