Skip to content

Instantly share code, notes, and snippets.

@H2CO3

H2CO3/my_vec.rs Secret

Created March 16, 2023 14:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save H2CO3/e997ede3b6bb064b8a438f3b7ef90be3 to your computer and use it in GitHub Desktop.
Save H2CO3/e997ede3b6bb064b8a438f3b7ef90be3 to your computer and use it in GitHub Desktop.
struct MyVec<T> {
pointer: *mut T,
capacity: usize,
length: usize
}
impl<T> MyVec<T> {
fn with_capacity(capacity: usize) -> Self {
let size = core::mem::size_of::<T>();
let pointer = if capacity == 0 {
size as *mut T // malloc(0) might return null, which is not allowed in a Vec
} else {
unsafe { libc::malloc(size * capacity) as *mut _ }
};
assert!(!pointer.is_null());
MyVec {
pointer,
capacity,
length: 0
}
}
fn new() -> Self {
Self::with_capacity(0)
}
fn len(&self) -> usize {
self.length
}
fn capacity(&self) -> usize {
self.capacity
}
fn push(&mut self, value: T) {
if self.length == self.capacity {
// need to grow and reallocate
self.capacity = core::cmp::max(self.capacity * 2, 1);
unsafe {
let new_pointer = libc::malloc(core::mem::size_of::<T>() * self.capacity) as *mut T;
core::ptr::copy_nonoverlapping(self.pointer, new_pointer, self.length);
if self.pointer as usize != core::mem::size_of::<T>() {
libc::free(self.pointer as *mut _);
}
self.pointer = new_pointer;
};
assert!(!self.pointer.is_null());
}
unsafe {
core::ptr::write(self.pointer.offset(self.length as isize), value);
}
self.length += 1;
}
fn pop(&mut self) -> Option<T> {
if self.length == 0 {
return None;
}
self.length -= 1;
Some(unsafe {
core::ptr::read(self.pointer.offset(self.length as isize))
})
}
fn as_slice(&self) -> &[T] {
unsafe {
core::slice::from_raw_parts(self.pointer, self.length)
}
}
fn as_slice_mut(&mut self) -> &mut [T] {
unsafe {
core::slice::from_raw_parts_mut(self.pointer, self.length)
}
}
}
impl<T> Drop for MyVec<T> {
fn drop(&mut self) {
unsafe {
for i in 0..self.length {
core::ptr::drop_in_place(self.pointer.offset(i as isize));
}
if self.pointer as usize != core::mem::size_of::<T>() {
libc::free(self.pointer as *mut _);
}
}
}
}
fn main() {
let mut v: MyVec<String> = MyVec::new();
v.push("foo".to_owned());
v.push("bar".to_owned());
v.push("qux".to_owned());
dbg!(v.as_slice());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment