-
-
Save H2CO3/e997ede3b6bb064b8a438f3b7ef90be3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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