Const Generic Arrays: A Type-Safe Fixed-Size Collection
Const generics in Rust allow you to define generic parameters that are evaluated at compile time, offering powerful ways to create more flexible and efficient code. This challenge focuses on leveraging const generics to implement a type-safe, fixed-size array-like data structure.
Problem Description
Your task is to implement a generic struct called ConstArray<T, const N: usize>. This struct should behave like a fixed-size array of elements of type T, where the size N is determined at compile time.
Key Requirements:
- Struct Definition: Define the
ConstArray<T, const N: usize>struct. It should internally hold a standard Rust array[T; N]to store its elements. - Creation: Implement a constructor function (e.g.,
new) that takes an array[T; N]as input and returns aConstArray. - Element Access: Implement an
indexmethod (or overload the[]operator using traits) that allows read-only access to elements by their index. This access should be bounds-checked at runtime. - Mutation: Implement a
index_mutmethod (or overload the[]operator for mutable access) that allows read-write access to elements by their index. This access should also be bounds-checked at runtime. - Length: Implement a
lenmethod that returns the sizeNof the array. - Iterator (Optional but Recommended): Implement an iterator that allows you to iterate over the elements of the
ConstArrayimmutably.
Expected Behavior:
- The size
Nof theConstArraymust be a constant value known at compile time. - Accessing elements within the valid bounds (0 to
N-1) should succeed. - Accessing elements outside these bounds should panic.
Edge Cases:
- Arrays of size 0.
- Arrays with different element types
T.
Examples
Example 1: Basic Usage
let mut my_array: ConstArray<i32, 5> = ConstArray::new([10, 20, 30, 40, 50]);
// Read-only access
assert_eq!(my_array[0], 10);
assert_eq!(my_array[2], 30);
// Mutable access
my_array[1] = 25;
assert_eq!(my_array[1], 25);
// Length
assert_eq!(my_array.len(), 5);
Explanation:
A ConstArray of 5 i32s is created. Elements are accessed and modified using their indices. The len() method correctly returns 5.
Example 2: Different Types and Size
let string_array: ConstArray<&str, 3> = ConstArray::new(["hello", "world", "rust"]);
assert_eq!(string_array[0], "hello");
assert_eq!(string_array.len(), 3);
Explanation:
Demonstrates that ConstArray can hold different types and that its size is determined by the const generic parameter.
Example 3: Edge Case - Zero Size Array
let empty_array: ConstArray<u8, 0> = ConstArray::new([]);
assert_eq!(empty_array.len(), 0);
// Accessing any index on an empty array should panic
// let _ = empty_array[0]; // This line would panic
Explanation:
An empty ConstArray is created. Its length is 0. Attempting to access any index on it would result in a panic, as expected for out-of-bounds access.
Constraints
- The const generic parameter
Nmust be ausize. - The element type
Tcan be any type that implementsCloneandCopyfor simplicity in the provided examples, but the core implementation should ideally work with anyT. For basic index access and mutation,CloneandCopyare not strictly required for the array's internal storage itself, but might be for the constructor if it takes a slice or similar. The problem focuses on the structure and genericity, so assumeT: Sizedis sufficient for the struct definition. - Runtime performance for element access and mutation should be comparable to standard Rust arrays.
Notes
- You will need to implement
std::ops::Indexandstd::ops::IndexMuttraits for the[]operator syntax. - For the optional iterator, consider implementing
IntoIteratorfor both mutable and immutable iteration. - The
newfunction could also be a direct struct instantiationConstArray { data: [...] }if preferred, but anewfunction is often clearer. - Consider how to handle initialization for arrays where
Tdoes not implementDefaultorCopy. For this challenge, assumeTisCopyor a simple initializer like an array literal is provided tonew.