Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 56 additions & 11 deletions project_3_vec/fast_vec/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ pub struct FastVec<T> {
impl<T> FastVec<T> {
// Creating a new FastVec that is either empty or has capacity for some future elements.
pub fn new() -> FastVec<T> {
return FastVec::with_capacity(1);
return FastVec::with_capacity(1); //will start with capacity 1 already
}
pub fn with_capacity(capacity: usize) -> FastVec<T> {
let ptr = unsafe { MALLOC.malloc(size_of::<T>() * 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,
Expand All @@ -29,7 +30,7 @@ impl<T> FastVec<T> {
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<T> {
let mut v = Vec::with_capacity(self.len);
for i in 0..self.len {
Expand All @@ -46,7 +47,7 @@ impl<T> FastVec<T> {
return v;
}

// Transforms a vector to a SlowVec.
// Transforms a vector to a FastVec.
pub fn from_vec(vec: Vec<T>) -> FastVec<T> {
let mut fast_vec: FastVec<T> = FastVec::with_capacity(vec.len());
for element in vec {
Expand All @@ -59,28 +60,72 @@ impl<T> FastVec<T> {
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::<T>()*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;
Expand Down
9 changes: 5 additions & 4 deletions project_3_vec/fast_vec/src/main.rs
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -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::<i32>()) 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));
Expand All @@ -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}");
}
Expand Down
44 changes: 32 additions & 12 deletions project_3_vec/slow_vec/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use fixed::FixedSizeArray;
// etc.
// look at main.rs for an example.
pub struct SlowVec<T> {
fixed: FixedSizeArray<T>,
fixed: FixedSizeArray<T>, //slowvecs are a fixed size array
}

// Functions inside SlowVec.
Expand All @@ -27,43 +27,63 @@ impl<T> SlowVec<T> {

// Transforms an instance of SlowVec to a regular vector.
pub fn into_vec(mut self) -> Vec<T> {
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<T>) -> SlowVec<T> {
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.
// Think of a reference as a read-only "copy" of the element.
// 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<T> = 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;
}
}

Expand Down
14 changes: 9 additions & 5 deletions project_3_vec/slow_vec/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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?
Expand Down