RustArena

Step 4 of 6

Implementing Display

{} in println! and format! works with any type that implements the standard trait std::fmt::Display. Numbers and strings implement it; your types don't, until you write it. You met this briefly for error types; here's the full picture.

use std::fmt;

struct Money {
    cents: i64,
}

impl fmt::Display for Money {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let sign = if self.cents < 0 { "-" } else { "" };
        let abs = self.cents.abs();
        write!(f, "{}${}.{:02}", sign, abs / 100, abs % 100)
    }
}

fn main() {
    let price = Money { cents: 1205 };
    let refund = Money { cents: -350 };
    println!("Price: {price}");
    println!("Refund: {}", refund);
    let text = price.to_string();
    println!("{} characters", text.len());
}
Price: $12.05
Refund: -$3.50
6 characters

Piece by piece:

Display or Debug?

Debug ({:?}) is for developers: derive it on almost every type and get a faithful dump of the fields. Display ({}) is for users: you choose the exact format, so it can't be derived. Should Money show $12.05, 12.05 USD or 12,05 €? Only you know.

Several lines? Use writeln!(f, ...)?; for each line except the last, then end with write!. The ? passes a formatting error on, like you did with Result in the errors module.

Common mistakes

use std::fmt;

struct Tag(String);

impl fmt::Display for Tag {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "#{}", self.0);
    }
}

fn main() {
    println!("{}", Tag(String::from("rust")));
}
error[E0308]: mismatched types

Your task

Implement Display for Temperature so it shows the value with one decimal place followed by °C: 21.5°C, -3.0°C.

Challenge 2

Race results. Implement Display for RaceTime (a number of seconds) so it shows m:ss under an hour, like 1:05 or 0:09, and h:mm:ss from one hour on, like 1:01:05. Minutes and seconds after the first number always have two digits.

Challenge 3

Playing cards. Implement Display for both types:

Inside Card's fmt you can use {} on self.suit, because Suit implements Display too.

Previous: Traits as parameters: bounds and impl Trait Next: Multiple bounds, where clauses and returning impl Trait