Last active
February 17, 2023 12:59
-
-
Save DutchGhost/fcee4e9074860eac5d3c5538aae96c6d to your computer and use it in GitHub Desktop.
const vec
This file contains hidden or 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
#![feature(const_ptr_is_null)] | |
#![feature(const_ptr_write)] | |
#![feature(const_mut_refs)] | |
#![feature(core_intrinsics)] | |
#![feature(inline_const)] | |
#![feature(const_heap)] | |
use core::intrinsics::{const_allocate, const_deallocate}; | |
struct CVec<T> { | |
ptr: *mut T, | |
len: usize, | |
cap: usize, | |
} | |
impl<T> CVec<T> { | |
const fn new() -> Self { | |
Self { | |
ptr: core::ptr::null_mut(), | |
len: 0, | |
cap: 0, | |
} | |
} | |
const fn push(&mut self, elem: T) { | |
if self.needs_grow() { | |
self.grow() | |
} | |
unsafe { | |
let offset = self.ptr.offset(self.len as isize); | |
core::ptr::write(offset, elem); | |
self.len += 1; | |
} | |
} | |
const fn as_slice(self) -> &'static [T] { | |
unsafe { core::slice::from_raw_parts(self.ptr, self.len) } | |
} | |
const fn needs_grow(&self) -> bool { | |
self.len == self.cap | |
} | |
const fn grow(&mut self) { | |
unsafe { | |
let new_cap = if self.cap == 0 { 4 } else { self.cap * 2 }; | |
self.cap = new_cap; | |
let ptr = const_allocate( | |
core::mem::size_of::<T>() * self.cap, | |
core::mem::align_of::<T>(), | |
); | |
if ptr.is_null() { | |
panic!("OH NO") | |
} | |
let ptr = ptr.cast(); | |
if self.len != 0 { | |
core::ptr::copy(self.ptr, ptr, self.len); | |
} | |
if !self.ptr.is_null() { | |
const_deallocate( | |
self.ptr.cast(), | |
core::mem::size_of::<T>() * self.len, | |
core::mem::align_of::<T>(), | |
); | |
} | |
self.ptr = ptr; | |
} | |
} | |
} | |
const X: &[i32] = { | |
let mut v = CVec::<i32>::new(); | |
v.push(20); | |
v.push(30); | |
v.push(40); | |
v.push(50); | |
v.push(60); | |
v.as_slice() | |
}; | |
fn main() { | |
dbg!(X); | |
} |
This file contains hidden or 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
#![feature(nonnull_slice_from_raw_parts)] | |
#![feature(ptr_as_uninit)] | |
#![feature(core_intrinsics)] | |
#![feature(const_slice_from_raw_parts_mut)] | |
#![feature(const_mut_refs)] | |
use core::{ | |
mem::MaybeUninit, | |
ptr::NonNull, | |
slice, | |
intrinsics::{const_allocate, const_deallocate} | |
}; | |
struct CVec<T> { | |
vec: NonNull<[MaybeUninit<T>]>, | |
idx: usize, | |
} | |
impl <T> CVec<T> { | |
pub const fn new() -> Self { | |
Self { | |
vec: NonNull::<[MaybeUninit<T>; 0]>::dangling(), | |
idx: 0 | |
} | |
} | |
pub const fn len(&self) -> usize { | |
self.idx | |
} | |
pub const fn capacity(&self) -> usize { | |
self.vec.len() | |
} | |
pub const fn push(&mut self, elem: T) { | |
if self.needs_grow() { | |
self.grow() | |
} | |
let mut slice = self.as_uninit_slice_mut(); | |
let place = self.idx; | |
slice[place] = MaybeUninit::new(elem); | |
} | |
} | |
impl <T> CVec<T> { | |
const fn needs_grow(&self) -> bool { | |
self.idx == self.vec.len() | |
} | |
const fn as_uninit_slice_mut(&mut self) -> &mut [MaybeUninit<T>] { | |
unsafe { slice::from_raw_parts_mut(self.vec.cast().as_ptr(), self.vec.len()) } | |
} | |
const unsafe fn grow(&mut self) { | |
let new_cap = match self.capacity() { | |
0 => 4, | |
n => n * 2 | |
}; | |
let ptr = const_allocate( | |
core::mem::size_of::<T>() * self.cap, | |
core::mem::align_of::<T>(), | |
); | |
if ptr.is_null() { | |
panic!("Not in const environment!"); | |
} | |
let ptr = ptr.cast(); | |
let ptr = NonNull::new_unchecked(ptr); | |
let slice = NonNull::slice_from_raw_parts(ptr, new_cap); | |
let new_slice = slice.as_uninit_slice_mut(); | |
let old_slice = self.vec.as_uninit_slice_mut(); | |
// memcpy | |
} | |
} |
This file contains hidden or 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
#![feature(const_for)] | |
#![feature(slice_ptr_get)] | |
#![feature(const_trait_impl)] | |
#![feature(const_ptr_as_ref)] | |
#![feature(const_nonnull_slice_from_raw_parts)] | |
#![feature(const_ptr_is_null)] | |
#![feature(const_heap)] | |
#![feature(nonnull_slice_from_raw_parts)] | |
#![feature(ptr_as_uninit)] | |
#![feature(core_intrinsics)] | |
#![feature(const_slice_from_raw_parts_mut)] | |
#![feature(const_mut_refs)] | |
use core::{ | |
intrinsics::{const_allocate, const_deallocate}, | |
mem::MaybeUninit, | |
ops::{Deref, DerefMut}, | |
ptr::NonNull, | |
slice, | |
}; | |
struct CVec<T> { | |
vec: NonNull<[MaybeUninit<T>]>, | |
idx: usize, | |
} | |
impl<T> CVec<T> { | |
pub const fn new() -> Self { | |
Self { | |
vec: NonNull::<[MaybeUninit<T>; 0]>::dangling(), | |
idx: 0, | |
} | |
} | |
pub const fn len(&self) -> usize { | |
self.idx | |
} | |
pub const fn capacity(&self) -> usize { | |
self.vec.len() | |
} | |
pub const fn push(&mut self, elem: T) { | |
if self.needs_grow() { | |
unsafe { self.grow() } | |
} | |
let place = self.idx; | |
let slice = self.as_uninit_slice_mut(); | |
slice[place] = MaybeUninit::new(elem); | |
self.idx += 1; | |
} | |
pub const fn into_slice(self) -> &'static [T] { | |
unsafe { | |
let ptr = self.vec.as_ptr().cast::<T>(); | |
core::slice::from_raw_parts(ptr, self.len()) | |
} | |
} | |
} | |
impl<T> const Deref for CVec<T> { | |
type Target = [T]; | |
fn deref(&self) -> &Self::Target { | |
self.as_slice_ref() | |
} | |
} | |
impl<T> const DerefMut for CVec<T> { | |
fn deref_mut(&mut self) -> &mut Self::Target { | |
self.as_slice_ref_mut() | |
} | |
} | |
impl<T> CVec<T> { | |
const fn needs_grow(&self) -> bool { | |
self.idx == self.vec.len() | |
} | |
const fn as_uninit_slice_mut(&mut self) -> &mut [MaybeUninit<T>] { | |
unsafe { slice::from_raw_parts_mut(self.vec.cast().as_ptr(), self.vec.len()) } | |
} | |
const fn as_slice_ref(&self) -> &[T] { | |
unsafe { | |
let ptr = self.vec.as_ptr().cast::<T>(); | |
core::slice::from_raw_parts(ptr, self.len()) | |
} | |
} | |
const fn as_slice_ref_mut(&mut self) -> &mut [T] { | |
unsafe { | |
let ptr = self.vec.as_mut_ptr().cast::<T>(); | |
core::slice::from_raw_parts_mut(ptr, self.len()) | |
} | |
} | |
const unsafe fn grow(&mut self) { | |
let new_cap = match self.capacity() { | |
0 => 4, | |
n => n * 2, | |
}; | |
let ptr = const_allocate( | |
core::mem::size_of::<T>() * new_cap, | |
core::mem::align_of::<T>(), | |
); | |
if ptr.is_null() { | |
panic!("Not in const environment!"); | |
} | |
let ptr = ptr.cast(); | |
let ptr = NonNull::new_unchecked(ptr); | |
let slice = NonNull::slice_from_raw_parts(ptr, new_cap); | |
let new_slice = slice.as_uninit_slice_mut(); | |
let old_slice = self.vec.as_uninit_slice_mut(); | |
let new_ptr = new_slice.as_mut_ptr(); | |
let old_ptr = old_slice.as_mut_ptr(); | |
core::ptr::copy(old_ptr, new_ptr, self.idx); | |
self.vec = slice; | |
// if self.len() is 0 there were no elements pushed, | |
// nothing to deallocate!! | |
if !old_ptr.is_null() && self.len() != 0 { | |
const_deallocate( | |
old_ptr.cast(), | |
core::mem::size_of::<T>() * self.len(), | |
core::mem::align_of::<T>(), | |
); | |
} | |
} | |
} | |
const X: &[i32] = { | |
let mut cv = CVec::new(); | |
cv.push(10); | |
cv.push(30); | |
cv.push(40); | |
cv.push(50); | |
cv.push(60); | |
cv.into_slice() | |
}; | |
fn main() { | |
dbg!(X); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment