What would happen in a use case like this?
use std::cell::UnsafeCell;
use std::alloc::{alloc, dealloc, Layout, handle_alloc_error};
use std::ptr;
pub struct UnsafeCellBox<T, const N: usize> {
value: UnsafeCell<Box<([T; N], usize)>>,
}
impl<T: Copy, const N: usize> UnsafeCellBox<T, N> {
pub fn new(val: [T; N]) -> Self {
Self {
value: UnsafeCell::new(Box::new((val, N))),
}
}
pub fn push(&self, val: T) {
unsafe {
let inner = &mut *self.value.get();
if inner.1 < N {
inner.0[inner.1] = val;
inner.1 += 1;
}
}
}
pub fn get(&self) -> &[T; N] {
unsafe {
&(*self.value.get()).0
}
}
}
pub struct RawPointer<T, const N: usize> {
ptr: *mut ([T; N], usize),
}
impl<T: Copy, const N: usize> RawPointer<T, N> {
pub fn new(val: [T; N]) -> Self {
let layout = Layout::new::<([T; N], usize)>();
unsafe {
let ptr = alloc(layout) as *mut ([T; N], usize);
if ptr.is_null() {
handle_alloc_error(layout);
}
ptr::write(ptr, (val, N));
Self { ptr }
}
}
pub fn push(&mut self, val: T) {
unsafe {
if (*self.ptr).1 < N {
(*self.ptr).0[(*self.ptr).1] = val;
(*self.ptr).1 += 1;
}
}
}
pub fn get(&self) -> &[T; N] {
unsafe {
&(*self.ptr).0
}
}
}
impl<T, const N: usize> Drop for RawPointer<T, N> {
fn drop(&mut self) {
unsafe {
ptr::drop_in_place(self.ptr);
dealloc(self.ptr as *mut u8, Layout::new::<([T; N], usize)>());
}
}
}
pub struct BoxStruct<T, const N: usize> {
inner: Box<([T; N], usize)>,
}
impl<T: Copy, const N: usize> BoxStruct<T, N> {
pub fn new(val: [T; N]) -> Self {
Self {
inner: Box::new((val, N)),
}
}
pub fn push(&mut self, val: T) {
if self.inner.1 < N {
self.inner.0[self.inner.1] = val;
self.inner.1 += 1;
}
}
pub fn get(&self) -> &[T; N] {
&self.inner.0
}
}
pub struct BoxUnsafeCell<T, const N: usize> {
inner: Box<UnsafeCell<([T; N], usize)>>,
}
impl<T: Copy, const N: usize> BoxUnsafeCell<T, N> {
pub fn new(val: [T; N]) -> Self {
Self {
inner: Box::new(UnsafeCell::new((val, N))),
}
}
pub fn push(&self, val: T) {
unsafe {
let inner = &mut *self.inner.get();
if inner.1 < N {
inner.0[inner.1] = val;
inner.1 += 1;
}
}
}
pub fn get(&self) -> &[T; N] {
unsafe {
&(*self.inner.get()).0
}
}
}
fn main() {
let initial = [1, 2, 0, 0];
let uc_box = UnsafeCellBox::<i32, 4>::new(initial);
uc_box.push(3);
println!("UnsafeCellBox: {:?}", uc_box.get());
let mut rp = RawPointer::<i32, 4>::new(initial);
rp.push(3);
println!("RawPointer: {:?}", rp.get());
let mut b = BoxStruct::<i32, 4>::new(initial);
b.push(3);
println!("BoxStruct: {:?}", b.get());
let buc = BoxUnsafeCell::<i32, 4>::new(initial);
buc.push(3);
println!("BoxUnsafeCell: {:?}", buc.get());
}