From f9bf6c513a7e94217595e9fb2fc5fb560d6addff Mon Sep 17 00:00:00 2001 From: kedcoa Date: Sat, 6 Jun 2026 15:01:58 -0400 Subject: [PATCH] Project 3 Code --- project_3_vec/fast_vec/src/lib.rs | 67 +++++++++++++++++++++++++----- project_3_vec/fast_vec/src/main.rs | 9 ++-- project_3_vec/slow_vec/src/lib.rs | 44 ++++++++++++++------ project_3_vec/slow_vec/src/main.rs | 14 ++++--- 4 files changed, 102 insertions(+), 32 deletions(-) diff --git a/project_3_vec/fast_vec/src/lib.rs b/project_3_vec/fast_vec/src/lib.rs index 5fc606d..1a4b546 100644 --- a/project_3_vec/fast_vec/src/lib.rs +++ b/project_3_vec/fast_vec/src/lib.rs @@ -10,10 +10,11 @@ pub struct FastVec { impl FastVec { // Creating a new FastVec that is either empty or has capacity for some future elements. pub fn new() -> FastVec { - return FastVec::with_capacity(1); + return FastVec::with_capacity(1); //will start with capacity 1 already } pub fn with_capacity(capacity: usize) -> FastVec { let ptr = unsafe { MALLOC.malloc(size_of::() * capacity) as *mut T }; + //size of space allocated on heap is size of new element * capacity you want return FastVec { ptr_to_data: ptr, len: 0, @@ -29,7 +30,7 @@ impl FastVec { return self.capacity; } - // Transforms an instance of SlowVec to a regular vector. + // Transforms an instance of FastVec to a regular vector. pub fn into_vec(mut self) -> Vec { let mut v = Vec::with_capacity(self.len); for i in 0..self.len { @@ -46,7 +47,7 @@ impl FastVec { return v; } - // Transforms a vector to a SlowVec. + // Transforms a vector to a FastVec. pub fn from_vec(vec: Vec) -> FastVec { let mut fast_vec: FastVec = FastVec::with_capacity(vec.len()); for element in vec { @@ -59,28 +60,72 @@ impl FastVec { return fast_vec; } - // Use the project handout as a guide for this part! pub fn get(&self, i: usize) -> &T { - todo!("implement get!"); + if i>= self.len() { + panic!("FastVec: get out of bounds"); + } else { + unsafe { + let value = &*self.ptr_to_data.add(i); //dereferences pointer to value + return value; + } //can't use read b/c you want to reference the value not move it + } } pub fn push(&mut self, t: T) { - if self.len == self.capacity { - todo!("implement growing the vector by doubling the size!"); - } else { - todo!("implement pushing t directly since the vector still has capacity!"); + if self.len == self.capacity { + let new_cap = self.capacity *2 ; //double the current capacity + let new_ptr = unsafe { MALLOC.malloc(size_of::()*new_cap) as *mut T }; + + //move all elements into new_cap; + for i in 0..self.len() { + unsafe { + //first move values out from old fastvec + let value = ptr::read(self.ptr_to_data.add(i)); //read value b/c moving it + //then write values into new fastvec + ptr::write(new_ptr.add(i),value); + } + } + //free the old fastvec space + unsafe {MALLOC.free(self.ptr_to_data as *mut u8); } + //update self.ptr to become new_ptr + self.ptr_to_data = new_ptr; + //update the capacity + self.capacity = new_cap; + } //now it has cap, push the value directly + unsafe { + ptr::write(self.ptr_to_data.add(self.len), t); } + self.len += 1; //always manually update len } pub fn remove(&mut self, i: usize) { - todo!("implement remove"); + if i >= self.len { + panic!("FastVec: remove out of bounds!"); + } + unsafe { + //move out the element at index + ptr::read(self.ptr_to_data.add(i)); + //shift all elements after index value to fill in gap + for j in (i+1)..self.len { + let value = ptr::read(self.ptr_to_data.add(j)); + ptr::write(self.ptr_to_data.add(j-1), value); + } + } + self.len -= 1; //manually update the length } // This appears correct but with further testing, you will notice it has a bug! // Hint: check out case 2 in memory.rs, which you can run using // cargo run --bin memory pub fn clear(&mut self) { - unsafe { MALLOC.free(self.ptr_to_data as *mut u8); } + //have to read (move) the values out first + unsafe { + for i in 0..self.len { + ptr::read(self.ptr_to_data.add(i)); + } + //and then you can free the empty fastvec + MALLOC.free(self.ptr_to_data as *mut u8); + } self.ptr_to_data = null_mut(); self.len = 0; self.capacity = 0; diff --git a/project_3_vec/fast_vec/src/main.rs b/project_3_vec/fast_vec/src/main.rs index e24b34b..71fc10d 100644 --- a/project_3_vec/fast_vec/src/main.rs +++ b/project_3_vec/fast_vec/src/main.rs @@ -1,6 +1,6 @@ use malloc::MALLOC; use fast_vec::FastVec; -use std::ptr; +use std::{io::ErrorKind::QuotaExceeded, ptr}; // This is a scratch pad for you. // Feel free to use it to try the different APIs and see if they work. @@ -21,9 +21,10 @@ fn malloc_and_ptr() { println!("address of pointer is {ptr1:p}"); } - // Malloc many values. + // Malloc 5 elements println!("malloc_and_ptr------"); let ptr2 = unsafe { MALLOC.malloc(5 * size_of::()) as *mut i32 }; + //this code is for actually writing in the values for i in 0..5 { unsafe { ptr::write(ptr2.add(i), 10 * (i as i32)); @@ -32,8 +33,8 @@ fn malloc_and_ptr() { for i in 0..5 { unsafe { - let tmp = ptr2.add(i); - let value = *tmp; + let tmp = ptr2.add(i); //temporary pointer for index location + let value = *tmp; //dereference to equal value at temp pointer println!("value at index {i} is {value}"); println!("address of index {i} is {tmp:p}"); } diff --git a/project_3_vec/slow_vec/src/lib.rs b/project_3_vec/slow_vec/src/lib.rs index 928bd6d..b61da85 100644 --- a/project_3_vec/slow_vec/src/lib.rs +++ b/project_3_vec/slow_vec/src/lib.rs @@ -9,7 +9,7 @@ use fixed::FixedSizeArray; // etc. // look at main.rs for an example. pub struct SlowVec { - fixed: FixedSizeArray, + fixed: FixedSizeArray, //slowvecs are a fixed size array } // Functions inside SlowVec. @@ -27,27 +27,27 @@ impl SlowVec { // Transforms an instance of SlowVec to a regular vector. pub fn into_vec(mut self) -> Vec { - let mut v = Vec::with_capacity(self.fixed.len()); + let mut v = Vec::with_capacity(self.fixed.len()); //make a new vec with the size of the SlowVec for i in 0..self.fixed.len() { - v.push(self.fixed.move_out(i)); + v.push(self.fixed.move_out(i)); //push elements of SlowVec into new vec } v } // Transforms a vector to a SlowVec. pub fn from_vec(vec: Vec) -> SlowVec { - let mut tmp = FixedSizeArray::allocate(vec.len()); - let mut index = 0; + let mut tmp = FixedSizeArray::allocate(vec.len()); //create a new SlowVec + let mut index = 0; for element in vec { - tmp.put(element, index); - index = index + 1; + tmp.put(element, index); //put element into new Slowvec + index = index + 1; //index as counter } return SlowVec { fixed: tmp }; } // Clear the content of this vector. pub fn clear(&mut self) { - self.fixed = FixedSizeArray::allocate(0); + self.fixed = FixedSizeArray::allocate(0); //equate current SlowVec with new slowvec of len 0 } // Get a reference to the element at position i. @@ -55,15 +55,35 @@ impl SlowVec { // We will talk about what references are in class. // Note: the element remains stored in the SlowVec after get(). It is not removed. pub fn get(&self, i: usize) -> &T { - self.fixed.get(i) + self.fixed.get(i) //fixed size array get returns a reference } pub fn push(&mut self, t: T) { - todo!() + //1. create new SlowVec with +1 len + let mut tmp: FixedSizeArray = FixedSizeArray::allocate(self.fixed.len()+1); + + //2. push old elements from self into tmp + for i in 0..(self.fixed.len()) { + tmp.put(self.fixed.move_out(i), i); //move_out b/c tmp needs to own elements, but elements currently owned by self.fixed + } + //3. add new element T into tmp + tmp.put(t, self.fixed.len()); + self.fixed = tmp; //update it } - pub fn remove(&mut self, i: usize) { - todo!() + pub fn remove(& mut self, i: usize) { + //1. create new SlowVec with -1 len + let mut tmp = FixedSizeArray::allocate(self.fixed.len()-1); + + //2. push old elements from self into tmp from 0 up to index + for j in 0..i { + tmp.put(self.fixed.move_out(j), j); //move out b/c + } + //3. skip adding old element at index and continue from after that index + for j in (i+1)..self.fixed.len() { + tmp.put(self.fixed.move_out(j), j-1); + } + self.fixed = tmp; } } diff --git a/project_3_vec/slow_vec/src/main.rs b/project_3_vec/slow_vec/src/main.rs index 73ae693..45ccd7f 100644 --- a/project_3_vec/slow_vec/src/main.rs +++ b/project_3_vec/slow_vec/src/main.rs @@ -13,15 +13,19 @@ fn fixed_sized_array() { array.put(20, 1); println!("{array}"); // You can print a FixedSizeArray directly! - // We can call get many times. + // We can call get many times b/c it's a reference! println!("{}", array.get(0)); println!("{}", array.get(0)); - // Can we call move many times? try it out and see for yourself. - println!("{}", array.move_out(0)); - // println!("{}", array.move_out(0)); - + //Cannot call move many times b/c it removes element out of array! + println!("{}", array.move_out(0)); + println!("{}", array.move_out(1)); + array.put(30, 0); + println!("{array}"); //outputs Fixed[30, % + // Try other things! + //println!("{}", array.get(0)); + //array.put(30,2); says index is out of bounds // What happens if you try to put or get things out of the range? // What happens if you try to get or move_out before put? // What if you try to get something you had move_out before?