Implementing Generic Data Structures with Trait Specialization in Rust
This challenge focuses on understanding and implementing a core concept in Rust's generics: trait specialization. You will build a simple data structure that can behave differently based on the type of data it holds, demonstrating how to specialize trait implementations for specific types. This is crucial for optimizing performance and providing type-specific behavior in generic code.
Problem Description
Your task is to create a generic Container struct in Rust. This Container should be able to store a single value of any type T. You will then define a trait, let's call it DisplayInfo, which has a method display_details().
The display_details() method should provide a generic output for most types. However, you need to specialize the implementation of DisplayInfo for String and i32 types to provide more specific and informative output.
Requirements:
- Generic
Container<T>struct: This struct should hold a single value of typeT. DisplayInfotrait:- Define a trait
DisplayInfowith a methodfn display_details(&self);. - This method should take
&selfand print information to the console.
- Define a trait
- Generic
DisplayInfoimplementation: Provide a default implementation ofDisplayInfofor any typeTthat implements thestd::fmt::Debugtrait. This implementation should print a message like "Generic container holds: [debug representation]". - Specialized
DisplayInfoforString: ImplementDisplayInfospecifically forContainer<String>. This implementation should print a message like "String container holds: [string value] (Length: [string length])". - Specialized
DisplayInfofori32: ImplementDisplayInfospecifically forContainer<i32>. This implementation should print a message like "Integer container holds: [integer value] (Is even: [true/false])". - Demonstrate usage: Create instances of
Containerwith different types (String,i32, and another generic type likef64) and call theirdisplay_details()methods to show the specialized and generic behaviors.
Expected Behavior:
- When
display_details()is called on aContainer<String>, the specializedStringoutput should be printed. - When
display_details()is called on aContainer<i32>, the specializedi32output should be printed. - When
display_details()is called on aContainerof any other type (e.g.,f64) that implementsDebug, the generic output should be printed.
Edge Cases:
- Ensure the
Containercan handle various types, including primitive types and user-defined types (as long as they implementDebugfor the generic case).
Examples
Example 1:
Input:
let string_container = Container { value: String::from("Hello, Rust!") };
string_container.display_details();
Output:
String container holds: Hello, Rust! (Length: 12)
Explanation: The input is a Container holding a String. The specialized String implementation of display_details is called, printing the string value and its length.
Example 2:
Input:
let int_container = Container { value: 42 };
int_container.display_details();
Output:
Integer container holds: 42 (Is even: true)
Explanation: The input is a Container holding an i32. The specialized i32 implementation of display_details is called, printing the integer value and whether it's even.
Example 3:
Input:
let float_container = Container { value: 3.14 };
float_container.display_details();
Output:
Generic container holds: 3.14
Explanation: The input is a Container holding an f64. Since f64 doesn't have a specific specialization, the generic DisplayInfo implementation is used, leveraging the Debug trait.
Constraints
- The
Containerstruct must be generic over a single type parameterT. - The
DisplayInfotrait must have exactly one method:display_details(&self). - The generic implementation of
DisplayInfoshould only apply whenTimplementsstd::fmt::Debug. - The specialized implementations must be for
Container<String>andContainer<i32>specifically.
Notes
This challenge directly relates to Rust's trait system and how it handles different implementations for the same trait based on concrete types. Pay close attention to the syntax for implementing traits for generic structs and for specific types within a generic context. You will likely need to use features like impl Trait for GenericStruct<SpecificType>.