custom_float 0.3.1

Custom floating-point types
Documentation
use core::alloc::Layout;

use crate::util;


pub struct ConstArray<T>
{
    ptr: *mut T,
    len: usize
}

impl<T> ConstArray<T>
{
    pub const fn new() -> Self
    {
        Self {
            ptr: core::ptr::null_mut(),
            len: 0
        }
    }

    pub const fn len(&self) -> usize
    {
        self.len
    }

    const fn layout(len: usize) -> Layout
    {
        let layout = unsafe {
            Layout::for_value_raw(core::ptr::slice_from_raw_parts(core::ptr::null::<T>(), len))
        };
        match layout.align_to(layout.align().next_power_of_two())
        {
            Ok(l) => l,
            Err(_) => panic!("Invalid align.")
        }
    }

    pub const fn destruct(mut self)
    {
        self.clear();
    }

    pub const fn clear(&mut self)
    {
        util::panic_in_rt();
        let old_layout = ConstArray::<T>::layout(self.len);
        if !self.ptr.is_null()
        {
            unsafe {
                core::intrinsics::const_deallocate(self.ptr.cast(), old_layout.size(), old_layout.align());
            }
        }
        self.ptr = core::ptr::null_mut();
        self.len = 0;
    }

    pub const fn push(&mut self, value: T)
    {
        util::panic_in_rt();
        let new_len = self.len + 1;
        let old_layout = Self::layout(self.len);
        let new_layout = Self::layout(new_len);
        self.ptr = unsafe {
            let new_ptr = core::intrinsics::const_allocate(new_layout.size(), new_layout.align()).cast::<T>();
            if !self.ptr.is_null()
            {
                core::ptr::copy_nonoverlapping(self.ptr, new_ptr, self.len);
                core::intrinsics::const_deallocate(self.ptr.cast(), old_layout.size(), old_layout.align());
            }
            let dst = new_ptr.add(self.len);
            dst.write(value);
            new_ptr
        };
        self.len = new_len
    }

    pub const fn as_slice(&self) -> &[T]
    {
        let &Self {ptr, len} = self;
        if ptr.is_null()
        {
            return &[]
        }
        unsafe {
            core::slice::from_raw_parts(ptr, len)
        }
    }

    pub const fn leak(self) -> &'static [T]
    {
        let Self {ptr, len} = self;
        if ptr.is_null()
        {
            return &[]
        }
        unsafe {
            core::slice::from_raw_parts(ptr, len)
        }
    }
}