#![allow(dead_code)]
#![no_std]
extern crate alloc;
use alloc::{
alloc::{alloc, Layout, dealloc, handle_alloc_error},
fmt, fmt::{Debug, Display, Formatter},
slice::{self, },
};
use core::{
mem::size_of,
ops::{Index, IndexMut},
iter::{IntoIterator, Iterator},
clone::Clone,
};
pub struct Caja<T> {
length : usize,
data : *mut T,
}
pub struct CajaIterator<'a, T> {
caja: &'a Caja<T>,
index: usize,
}
pub struct CajaIteratorMut<'a, T> {
caja: &'a mut Caja<T>,
index: usize,
}
impl<T> Caja<T> {
pub unsafe fn new_uninitialized(size : usize) -> Self {
if size == 0 {
return Self {
length : 0,
data : core::ptr::null_mut()
};
}
let lay = Layout::array::<T>(size).unwrap();
let ptr = alloc(lay) as *mut T;
if ptr.is_null() {
handle_alloc_error(lay);
}
Self {
length : size,
data : ptr,
}
}
pub unsafe fn new_zeroed(size : usize) -> Self {
let c = Self::new_uninitialized(size);
for i in 0..size*size_of::<T>() {
*(c.data as *mut u8).add(i) = 0;
}
c
}
#[inline(always)]
pub fn as_mut_ptr(&self) -> *mut T {
self.data
}
#[inline(always)]
pub fn as_ptr(&self) -> *const T {
self.data
}
#[inline(always)]
pub fn len(&self) -> usize {
self.length
}
#[inline(always)]
pub fn as_slice(&self) -> &[T] {unsafe{
slice::from_raw_parts(self.data, self.length)
}}
#[inline(always)]
pub fn as_mut_slice(&self) -> &mut [T] {unsafe{
slice::from_raw_parts_mut(self.data, self.length)
}}
#[inline(always)]
pub unsafe fn unchecked_index<'a>(&self, index : usize) -> &'a T {
unsafe { self.data.add(index).as_ref().unwrap() }
}
#[inline(always)]
pub unsafe fn unchecked_index_mut<'a>(&mut self, index : usize) -> &'a mut T {
unsafe {self.data.add(index).as_mut().unwrap() }
}
}
impl<T> Drop for Caja<T> {
fn drop(&mut self) {unsafe{
dealloc(
self.data as *mut u8,
Layout::array::<T>(self.length).unwrap()
);
};}
}
impl<T> Index<usize> for Caja<T> {
type Output = T;
#[inline(always)]
fn index(&self, index : usize) -> &Self::Output {
assert!(self.length > index);
unsafe { self.data.add(index).as_ref().unwrap() }
}
}
impl<T> IndexMut<usize> for Caja<T> {
#[inline(always)]
fn index_mut(&mut self, index : usize) -> &mut Self::Output {
assert!(self.length > index);
unsafe { self.data.add(index).as_mut().unwrap() }
}
}
impl<'a, T> Iterator for CajaIterator<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
if self.caja.length > self.index {
let r = unsafe {
self.caja.unchecked_index(self.index)
};
self.index += 1;
Some(r)
} else { None }
}
}
impl<'a, T> Iterator for CajaIteratorMut<'a, T> {
type Item = &'a mut T;
fn next(&mut self) -> Option<Self::Item> {
if self.caja.length > self.index {
let r = unsafe {
self.caja.unchecked_index_mut(self.index)
};
self.index += 1;
Some(r)
} else { None }
}
}
impl<'a, T> IntoIterator for &'a Caja<T> {
type Item = &'a T;
type IntoIter = CajaIterator<'a, T>;
fn into_iter(self) -> Self::IntoIter {
CajaIterator {
caja: self,
index: 0,
}
}
}
impl<'a, T> IntoIterator for &'a mut Caja<T> {
type Item = &'a mut T;
type IntoIter = CajaIteratorMut<'a, T>;
fn into_iter(self) -> Self::IntoIter {
CajaIteratorMut {
caja: self,
index: 0,
}
}
}
impl<T : Display> Display for Caja<T> {
fn fmt(&self, format : &mut Formatter<'_>) -> fmt::Result {
let mut res = write!(format, "Length : {}\nData : [ ", self.length);
for i in 0..self.length-1 {
if res.is_err() {
return res;
}
res = write!(format, "{}, ", self[i]);
}
res = write!(format, "{} ]\n", self[self.length-1]);
res
}
}
impl<T : Debug> Debug for Caja<T> {
fn fmt(&self, format : &mut Formatter<'_>) -> fmt::Result {unsafe{
format.debug_struct("Caja")
.field("length", &self.length)
.field("data", &self.data)
.field("data as an array", &slice::from_raw_parts(self.data, self.length))
.finish()
}}
}
impl<T : Copy> Caja<T> {
pub fn new(size : usize, default : T) -> Self {
let mut c = unsafe { Self::new_uninitialized(size) };
for i in &mut c {
*i = default;
}
c
}
}
impl<T: Copy> Clone for Caja<T> {
fn clone(&self) -> Self {
let mut r = unsafe { Self::new_uninitialized(self.length) };
for i in 0..self.length {
r[i] = self[i];
}
r
}
}
impl<T : Copy> From<&[T]> for Caja<T> {
fn from(frm : &[T]) -> Self {
let mut ret = unsafe { Self::new_uninitialized(frm.len()) };
for i in 0..frm.len() {
ret[i] = frm[i];
}
ret
}
}