use std::{iter::FusedIterator, marker::PhantomData, mem, ptr::NonNull, slice};
use super::{Arena, CHUNK_FOOTER_SIZE, ChunkFooter};
impl<const MIN_ALIGN: usize> Arena<MIN_ALIGN> {
pub fn chunk_capacity(&self) -> usize {
let current_footer = self.current_chunk_footer.get();
let current_footer = unsafe { current_footer.as_ref() };
current_footer.cursor_ptr.get().as_ptr() as usize
- current_footer.start_ptr.as_ptr() as usize
}
pub fn iter_allocated_chunks(&mut self) -> ChunkIter<'_, MIN_ALIGN> {
let raw = unsafe { self.iter_allocated_chunks_raw() };
ChunkIter { raw, arena: PhantomData }
}
pub unsafe fn iter_allocated_chunks_raw(&self) -> ChunkRawIter<'_, MIN_ALIGN> {
ChunkRawIter { footer: self.current_chunk_footer.get(), arena: PhantomData }
}
pub fn allocated_bytes(&self) -> usize {
let mut total = 0;
let mut footer_ptr = self.current_chunk_footer.get();
unsafe {
while !footer_ptr.as_ref().is_empty() {
total += footer_ptr.as_ref().layout.size() - CHUNK_FOOTER_SIZE;
footer_ptr = footer_ptr.as_ref().previous_chunk_footer_ptr.get();
}
}
total
}
}
#[derive(Debug)]
pub struct ChunkIter<'a, const MIN_ALIGN: usize = 1> {
raw: ChunkRawIter<'a, MIN_ALIGN>,
arena: PhantomData<&'a mut Arena<MIN_ALIGN>>,
}
impl<'a, const MIN_ALIGN: usize> Iterator for ChunkIter<'a, MIN_ALIGN> {
type Item = &'a [mem::MaybeUninit<u8>];
fn next(&mut self) -> Option<Self::Item> {
unsafe {
let (ptr, len) = self.raw.next()?;
let slice = slice::from_raw_parts(ptr as *const mem::MaybeUninit<u8>, len);
Some(slice)
}
}
}
impl<const MIN_ALIGN: usize> FusedIterator for ChunkIter<'_, MIN_ALIGN> {}
#[derive(Debug)]
pub struct ChunkRawIter<'a, const MIN_ALIGN: usize = 1> {
footer: NonNull<ChunkFooter>,
arena: PhantomData<&'a Arena<MIN_ALIGN>>,
}
impl<const MIN_ALIGN: usize> Iterator for ChunkRawIter<'_, MIN_ALIGN> {
type Item = (*mut u8, usize);
fn next(&mut self) -> Option<(*mut u8, usize)> {
unsafe {
let foot = self.footer.as_ref();
if foot.is_empty() {
return None;
}
let (ptr, len) = foot.as_raw_parts();
self.footer = foot.previous_chunk_footer_ptr.get();
Some((ptr, len))
}
}
}
impl<const MIN_ALIGN: usize> FusedIterator for ChunkRawIter<'_, MIN_ALIGN> {}