alloc/dealloc

This commit is contained in:
nora 2021-12-20 16:48:02 +01:00
parent 0764c02fa5
commit b6cd4a1d06
3 changed files with 102 additions and 6 deletions

View file

@ -1,2 +1,3 @@
[toolchain]
channel = "nightly-2021-12-19"
components = ["miri"]

View file

@ -1,5 +1,6 @@
#![no_std]
#![feature(ptr_metadata, ptr_internals)]
#![feature(ptr_metadata)]
#![deny(unsafe_op_in_unsafe_fn)]
//!
//! A `Vec<T: ?Sized>`
@ -32,15 +33,85 @@
//! |_________________________________________|
//! ```
mod test;
extern crate alloc;
use core::alloc::Layout;
use core::marker::PhantomData;
use core::ptr::{NonNull};
use alloc::vec::Vec;
use core::num::NonZeroUsize;
use core::ptr::NonNull;
/// chonky af
struct Vechonk<T: ?Sized> {
size: usize,
///
/// only works for copy types, but this is WIP and will be removed
pub struct Vechonk<T: ?Sized + Copy> {
ptr: NonNull<u8>,
len: usize,
cap: usize,
ptrs: Vec<NonNull<T>>
_marker: PhantomData<T>,
}
impl<T: ?Sized + Copy> Vechonk<T> {
pub fn len(&self) -> usize {
self.len
}
pub fn new() -> Self {
Self {
// SAFETY: 1 is not 0
ptr: unsafe { NonNull::new_unchecked(1 as *mut u8) },
len: 0,
cap: 0,
_marker: PhantomData,
}
}
pub fn with_capacity(capacity: usize) -> Self {
let mut vechonk = Self::new();
if capacity == 0 {
return vechonk;
}
// SAFETY: capacity has been checked to not be 0 and the len is 0
unsafe {
vechonk.grow_to(NonZeroUsize::new_unchecked(capacity));
}
vechonk
}
/// Grows the `Vechonk` to a new capacity. This will not copy any elements. This will put the `Vechonk`
/// into an invalid state, since the `len` is still the length of the old allocation.
///
/// # Safety
/// The caller must either set the `len` to zero, or copy the elements to the new allocation by saving
/// `self.ptr` before calling this function.
unsafe fn grow_to(&mut self, size: NonZeroUsize) {
// SAFETY: 1 is not 0 and a power of two. `size > usize::MAX` must always be true
let layout = unsafe { Layout::from_size_align_unchecked(size.get(), 1) };
// SAFETY: layout is guaranteed to have a non-zero size
let alloced_ptr = unsafe { alloc::alloc::alloc(layout) };
self.ptr =
NonNull::new(alloced_ptr).unwrap_or_else(|| alloc::alloc::handle_alloc_error(layout));
self.cap = size.get();
}
}
// we can only drop copy for now because destructors 🤮
impl<T: ?Sized + Copy> Drop for Vechonk<T> {
fn drop(&mut self) {
if self.cap == 0 {
return;
}
// SAFETY: 1 is not 0 and a power of two. `size > usize::MAX` must always be true
let layout = unsafe { Layout::from_size_align_unchecked(self.cap, 1) };
unsafe { alloc::alloc::dealloc(self.ptr.as_ptr(), layout) };
}
}

24
src/test.rs Normal file
View file

@ -0,0 +1,24 @@
#![cfg(test)]
use crate::Vechonk;
#[test]
fn new() {
let chonk = Vechonk::<()>::new();
assert_eq!(chonk.len(), 0);
}
#[test]
fn zero_capacity() {
let chonk = Vechonk::<()>::with_capacity(0);
assert_eq!(chonk.len(), 0);
}
#[test]
fn some_capacity() {
let chonk = Vechonk::<()>::with_capacity(100);
assert_eq!(chonk.len(), 0);
}