use std::marker::PhantomData;
use std::mem::ManuallyDrop;
use crate::buf::Alloc;
use crate::ty;
use crate::{BodyBuf, Signature, Storable};
use super::{StoreStruct, StoreVariant};
pub struct StoreArray<'a, T>
where
T: ty::Aligned,
{
buf: &'a mut BodyBuf,
len: Alloc<u32>,
start: usize,
_marker: PhantomData<T>,
}
impl<'a, T> StoreArray<'a, T>
where
T: ty::Aligned,
{
pub(crate) fn new(buf: &'a mut BodyBuf) -> Self {
let len = buf.alloc();
buf.align_mut::<T::Alignment>();
let start = buf.len();
Self {
buf,
start,
len,
_marker: PhantomData,
}
}
#[inline]
pub fn finish(self) {
ManuallyDrop::new(self).finalize();
}
#[inline(always)]
fn finalize(&mut self) {
let end = self.buf.len();
let len = (end - self.start) as u32;
self.buf.store_at(self.len, len);
}
}
impl<T> Drop for StoreArray<'_, T>
where
T: ty::Aligned,
{
#[inline]
fn drop(&mut self) {
self.finalize();
}
}
impl<T> StoreArray<'_, T>
where
T: ty::Aligned,
{
pub fn store(&mut self, value: T::Return<'_>)
where
T: ty::Marker,
for<'b> T::Return<'b>: Storable,
{
value.store_to(self.buf);
}
#[inline]
pub fn store_struct(&mut self) -> StoreStruct<'_, T>
where
T: ty::Fields,
{
StoreStruct::new(self.buf)
}
}
impl StoreArray<'_, ty::Variant> {
#[inline]
pub fn store_variant(&mut self, signature: &Signature) -> StoreVariant<'_> {
StoreVariant::new(self.buf, signature)
}
}
impl<K, V> StoreArray<'_, ty::Dict<K, V>>
where
K: ty::Marker,
V: ty::Marker,
{
#[inline]
pub fn store_entry(&mut self) -> StoreStruct<'_, (K, V)> {
StoreStruct::new(self.buf)
}
}
impl<T> StoreArray<'_, ty::Array<T>>
where
T: ty::Aligned,
{
#[inline]
pub fn store_array(&mut self) -> StoreArray<'_, T> {
StoreArray::new(self.buf)
}
}
impl StoreArray<'_, u8> {
#[inline]
pub fn write_slice(&mut self, bytes: &[u8]) {
self.buf.extend_from_slice(bytes);
}
}