Printable Types in Rust's Standard Library

RustRustBeginner
Practice Now

This tutorial is from open-source community. Access the source code

Introduction

In this lab, it is explained that in order to use the std::fmt formatting traits, types must have an implementation to be printable, which can be automatically provided for types in the std library. For other types, the fmt::Debug trait can be derived to enable printing. The fmt::Debug trait makes it straightforward to implement printable types, while fmt::Display needs to be manually implemented. The fmt::Debug trait allows all types to derive the implementation for printing, and the same applies to {:?} for std library types. The lab also mentions the use of {:?} for printing and provides an example of how to use it to print different types. Additionally, the concept of "pretty printing" with {:#?} is introduced, which provides a more elegant representation of data structures. Finally, it is mentioned that fmt::Display can be manually implemented to have control over the display of types.

Note: If the lab does not specify a file name, you can use any file name you want. For example, you can use main.rs, compile and run it with rustc main.rs && ./main.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL rust(("`Rust`")) -.-> rust/BasicConceptsGroup(["`Basic Concepts`"]) rust(("`Rust`")) -.-> rust/DataTypesGroup(["`Data Types`"]) rust(("`Rust`")) -.-> rust/FunctionsandClosuresGroup(["`Functions and Closures`"]) rust(("`Rust`")) -.-> rust/MemorySafetyandManagementGroup(["`Memory Safety and Management`"]) rust/BasicConceptsGroup -.-> rust/variable_declarations("`Variable Declarations`") rust/DataTypesGroup -.-> rust/integer_types("`Integer Types`") rust/DataTypesGroup -.-> rust/string_type("`String Type`") rust/FunctionsandClosuresGroup -.-> rust/function_syntax("`Function Syntax`") rust/FunctionsandClosuresGroup -.-> rust/expressions_statements("`Expressions and Statements`") rust/MemorySafetyandManagementGroup -.-> rust/lifetime_specifiers("`Lifetime Specifiers`") subgraph Lab Skills rust/variable_declarations -.-> lab-99187{{"`Printable Types in Rust's Standard Library`"}} rust/integer_types -.-> lab-99187{{"`Printable Types in Rust's Standard Library`"}} rust/string_type -.-> lab-99187{{"`Printable Types in Rust's Standard Library`"}} rust/function_syntax -.-> lab-99187{{"`Printable Types in Rust's Standard Library`"}} rust/expressions_statements -.-> lab-99187{{"`Printable Types in Rust's Standard Library`"}} rust/lifetime_specifiers -.-> lab-99187{{"`Printable Types in Rust's Standard Library`"}} end

Debug

All types which want to use std::fmt formatting traits require an implementation to be printable. Automatic implementations are only provided for types such as in the std library. All others must be manually implemented somehow.

The fmt::Debug trait makes this very straightforward. All types can derive (automatically create) the fmt::Debug implementation. This is not true for fmt::Display which must be manually implemented.

// This structure cannot be printed either with `fmt::Display` or
// with `fmt::Debug`.
struct UnPrintable(i32);

// The `derive` attribute automatically creates the implementation
// required to make this `struct` printable with `fmt::Debug`.
#[derive(Debug)]
struct DebugPrintable(i32);

All std library types are automatically printable with {:?} too:

// Derive the `fmt::Debug` implementation for `Structure`. `Structure`
// is a structure which contains a single `i32`.
#[derive(Debug)]
struct Structure(i32);

// Put a `Structure` inside of the structure `Deep`. Make it printable
// also.
#[derive(Debug)]
struct Deep(Structure);

fn main() {
    // Printing with `{:?}` is similar to with `{}`.
    println!("{:?} months in a year.", 12);
    println!("{1:?} {0:?} is the {actor:?} name.",
             "Slater",
             "Christian",
             actor="actor's");

    // `Structure` is printable!
    println!("Now {:?} will print!", Structure(3));

    // The problem with `derive` is there is no control over how
    // the results look. What if I want this to just show a `7`?
    println!("Now {:?} will print!", Deep(Structure(7)));
}

So fmt::Debug definitely makes this printable but sacrifices some elegance. Rust also provides "pretty printing" with {:#?}.

#[derive(Debug)]
struct Person<'a> {
    name: &'a str,
    age: u8
}

fn main() {
    let name = "Peter";
    let age = 27;
    let peter = Person { name, age };

    // Pretty print
    println!("{:#?}", peter);
}

One can manually implement fmt::Display to control the display.

Summary

Congratulations! You have completed the Debug lab. You can practice more labs in LabEx to improve your skills.

Other Rust Tutorials you may like