mirror of
https://github.com/Noratrieb/vechonk.git
synced 2026-01-14 16:45:10 +01:00
alloc/dealloc
This commit is contained in:
parent
0764c02fa5
commit
b6cd4a1d06
3 changed files with 102 additions and 6 deletions
|
|
@ -1,2 +1,3 @@
|
|||
[toolchain]
|
||||
channel = "nightly-2021-12-19"
|
||||
components = ["miri"]
|
||||
83
src/lib.rs
83
src/lib.rs
|
|
@ -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
24
src/test.rs
Normal 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);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue