Implementing Basic Vector Operations in Rust
This challenge focuses on implementing fundamental operations for a custom vector-like data structure in Rust. Understanding how to manage dynamic arrays and perform common manipulations is crucial for many programming tasks, from game development to data processing. You will build a simplified Vec that supports adding elements, accessing elements, and calculating its length.
Problem Description
Your task is to create a struct named MyVec that mimics some of the behavior of Rust's standard Vec<T>. This MyVec should be able to store elements of any type T. You will need to implement methods for:
- Initialization: Creating an empty
MyVec. - Adding Elements (
push): Appending a new element to the end of the vector. - Getting Length (
len): Returning the current number of elements in the vector. - Accessing Elements (
get): Retrieving an element at a specific index, returning anOption<&T>to handle out-of-bounds access gracefully.
The internal representation of MyVec can be a dynamically sized array (e.g., using Vec<T> internally, but you are building your own interface for it) or a raw pointer with manual memory management. For this challenge, using Vec<T> as the internal storage is acceptable for simplicity, focusing on the method implementations.
Examples
Example 1:
Input:
let mut my_vec: MyVec<i32> = MyVec::new();
my_vec.push(10);
my_vec.push(20);
Output:
my_vec.len() -> 2
my_vec.get(0) -> Some(&10)
my_vec.get(1) -> Some(&20)
Explanation:
We create an empty vector. Pushing 10 and 20 adds them to the vector.
The length is now 2. Getting the element at index 0 returns Some(&10), and at index 1 returns Some(&20).
Example 2:
Input:
let mut my_vec: MyVec<String> = MyVec::new();
my_vec.push("hello".to_string());
my_vec.push("world".to_string());
Output:
my_vec.len() -> 2
my_vec.get(0) -> Some(&"hello".to_string())
my_vec.get(2) -> None
Explanation:
We initialize a vector for Strings. Pushing "hello" and "world" populates it.
The length is 2. Accessing index 0 yields Some(&"hello".to_string()). Accessing index 2 is out of bounds, so it returns None.
Example 3:
Input:
let mut my_vec: MyVec<f64> = MyVec::new();
Output:
my_vec.len() -> 0
my_vec.get(0) -> None
Explanation:
An empty vector has a length of 0. Any attempt to get an element from an empty vector will result in None.
Constraints
- The
MyVec<T>struct should be generic over typeT. - The
pushoperation should be able to handle appending any element of typeT. - The
lenoperation must return ausize. - The
getoperation must returnOption<&T>and correctly handle out-of-bounds indices by returningNone. - The internal storage can be a
Vec<T>, but the goal is to implement the specified public API methods.
Notes
- Consider how Rust's ownership and borrowing rules apply when implementing the
getmethod to return a reference. - The
pushmethod will need to modify the internal state of theMyVec. - Think about the return types of each method.
- You will need to define the
MyVecstruct and implement the methods usingimpl<T> MyVec<T> { ... }.