#[derive(Clone, Debug)]
pub struct Layout {
size: usize,
align: usize,
}
pub struct LayoutBuilder {
size: usize,
align: usize,
}
impl Layout {
pub const fn of<T>() -> Self {
let std_layout = std::alloc::Layout::new::<T>();
Self::new(std_layout.size(), std_layout.align())
}
pub const fn new(size: usize, align: usize) -> Self {
assert!(align > 0);
assert!(align.is_power_of_two());
assert!(size.is_multiple_of(align));
Self { size, align }
}
pub const fn size(&self) -> usize {
self.size
}
pub const fn align(&self) -> usize {
self.align
}
pub const fn align_shift(&self) -> usize {
self.align.ilog2() as usize
}
pub fn union(&self, other: &Self) -> Self {
let size = self.size.max(other.size);
let align = self.align.max(other.align);
let size = size.next_multiple_of(align);
Self { size, align }
}
pub fn concat(iter: impl IntoIterator<Item = Self>) -> Self {
let mut builder = LayoutBuilder::new();
for layout in iter {
builder.add(&layout);
}
builder.finish()
}
pub fn offset_by(&self, n: usize) -> usize {
let mut builder = LayoutBuilder::new();
builder.add(&Layout::new(n, 1));
builder.add(self)
}
}
impl Default for LayoutBuilder {
fn default() -> Self {
Self::new()
}
}
impl LayoutBuilder {
pub fn new() -> Self {
Self { size: 0, align: 1 }
}
pub fn add(&mut self, layout: &Layout) -> usize {
let offset = self.size.next_multiple_of(layout.align());
self.align = self.align.max(layout.align());
self.size = offset + layout.size();
offset
}
pub fn finish(self) -> Layout {
let size = self.size.next_multiple_of(self.align);
Layout::new(size, self.align)
}
}