use super::DynamicAllocation;
use crate::{
collections::BitStash,
traits::{
KeyPtr,
SpreadLayout,
},
};
#[derive(Debug, Default, PartialEq, Eq)]
pub struct DynamicAllocator {
allocations: BitStash,
}
#[cfg(feature = "std")]
const _: () = {
use crate::traits::StorageLayout;
use pro_metadata::layout::{
FieldLayout,
Layout,
StructLayout,
};
impl StorageLayout for DynamicAllocator {
fn layout(key_ptr: &mut KeyPtr) -> Layout {
Layout::Struct(StructLayout::new(vec![FieldLayout::new(
"allocations",
<BitStash as StorageLayout>::layout(key_ptr),
)]))
}
}
};
impl SpreadLayout for DynamicAllocator {
const FOOTPRINT: u64 = <BitStash as SpreadLayout>::FOOTPRINT;
fn pull_spread(ptr: &mut KeyPtr) -> Self {
Self {
allocations: SpreadLayout::pull_spread(ptr),
}
}
fn push_spread(&self, ptr: &mut KeyPtr) {
SpreadLayout::push_spread(&self.allocations, ptr);
}
fn clear_spread(&self, ptr: &mut KeyPtr) {
SpreadLayout::clear_spread(&self.allocations, ptr);
}
}
impl DynamicAllocator {
pub fn alloc(&mut self) -> DynamicAllocation {
DynamicAllocation(self.allocations.put())
}
pub fn free(&mut self, allocation: DynamicAllocation) {
let index = allocation.get();
if !self
.allocations
.take(index)
.expect("invalid dynamic storage allocation")
{
panic!(
"encountered double free of dynamic storage: at index {}",
index
)
}
}
}