Implementing the Display Trait for Custom Types
In Rust, the std::fmt::Display trait is used to define how a type should be formatted for human-readable output, typically when using macros like println! or format!. This challenge will test your understanding of traits, generics, and how to implement custom formatting for your own data structures.
Problem Description
Your task is to implement the std::fmt::Display trait for a custom struct and an enum that you will define. This will allow instances of these types to be printed directly to the console using println! and formatted into strings using format!.
Key Requirements:
- Define a
struct: Create a simplestructthat holds a few fields (e.g.,name: String,id: u32). - Define an
enum: Create a simpleenumwith a few variants, some of which might hold data. - Implement
Displayfor thestruct: Implement thestd::fmt::Displaytrait for yourstruct. The output should be a human-readable string representing the struct's data. - Implement
Displayfor theenum: Implement thestd::fmt::Displaytrait for yourenum. The output should clearly indicate which variant is active and display its associated data if any. - Demonstrate usage: Write a
mainfunction that creates instances of yourstructandenumand prints them usingprintln!.
Expected Behavior:
When an instance of your struct is printed, it should produce a string that clearly represents its contents. For example, if a struct has name: "Alice" and id: 123, it might be displayed as "User { name: Alice, id: 123 }".
When an instance of your enum is printed, it should also clearly represent its variant and any data it holds. For example, if an enum has a variant Status(String) with the value "Active", it might be displayed as "Status: Active".
Edge Cases to Consider:
- Empty strings for fields.
- Enums with variants that hold no data.
- Enums with variants that hold different types of data (e.g., a
u32vs. aString).
Examples
Example 1: Struct Display
// Assume a struct `Point` is defined as:
// struct Point {
// x: i32,
// y: i32,
// }
//
// And `Display` is implemented to output:
// "Point { x: 5, y: -10 }"
Input:
let p = Point { x: 5, y: -10 };
println!("{}", p);
Output:
Point { x: 5, y: -10 }
Example 2: Enum Display
// Assume an enum `ResultStatus` is defined as:
// enum ResultStatus {
// Success(String),
// Error(u16),
// Pending,
// }
//
// And `Display` is implemented to output:
// For `Success("Operation complete")`: "Status: Success - Operation complete"
// For `Error(404)`: "Status: Error - Code 404"
// For `Pending`: "Status: Pending"
Input:
let res1 = ResultStatus::Success("Operation complete".to_string());
let res2 = ResultStatus::Error(404);
let res3 = ResultStatus::Pending;
println!("Result 1: {}", res1);
println!("Result 2: {}", res2);
println!("Result 3: {}", res3);
Output:
Result 1: Status: Success - Operation complete
Result 2: Status: Error - Code 404
Result 3: Status: Pending
Constraints
- Your
structmust have at least two fields. - Your
enummust have at least three variants, with at least one variant holding data. - The implementation of
Displayshould produce clear and unambiguous output. - You must use the
std::fmt::Formatterandstd::fmt::Resulttypes within yourfmtmethod.
Notes
- Remember to
use std::fmt;to bring the necessary traits and types into scope. - The
fmtmethod signature forDisplayisfn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result. - The
Formattertype provides methods likewrite_str(),debug_tuple(),debug_struct(), etc., which are very useful for formatting. You are encouraged to exploreFormatter's documentation. - Consider using
f.debug_struct("StructName")orf.debug_tuple("EnumVariantName")for more structured output, especially for your struct and enum variants.