use crate::PokeValueUninit;
use facet_core::{ListDef, ListVTable, Opaque, OpaqueConst, OpaqueUninit, Shape};
pub struct PokeListUninit<'mem> {
data: OpaqueUninit<'mem>,
shape: &'static Shape,
def: ListDef,
}
impl<'mem> PokeListUninit<'mem> {
#[inline(always)]
pub fn into_value(self) -> PokeValueUninit<'mem> {
unsafe { PokeValueUninit::new(self.data, self.shape) }
}
#[inline(always)]
pub fn shape(&self) -> &'static Shape {
self.shape
}
pub(crate) unsafe fn new(
data: OpaqueUninit<'mem>,
shape: &'static Shape,
def: ListDef,
) -> Self {
Self { data, shape, def }
}
pub fn init(self, size_hint: Option<usize>) -> Result<PokeList<'mem>, OpaqueUninit<'mem>> {
let res = if let Some(capacity) = size_hint {
let init_in_place_with_capacity = self.def.vtable.init_in_place_with_capacity;
unsafe { init_in_place_with_capacity(self.data, capacity) }
} else {
let pv = unsafe { PokeValueUninit::new(self.data, self.shape) };
pv.default_in_place().map_err(|_| ())
};
let data = res.map_err(|_| self.data)?;
Ok(unsafe { PokeList::new(data, self.shape, self.def) })
}
}
pub struct PokeList<'mem> {
data: Opaque<'mem>,
#[allow(dead_code)]
shape: &'static Shape,
def: ListDef,
}
impl<'mem> PokeList<'mem> {
pub(crate) unsafe fn new(data: Opaque<'mem>, shape: &'static Shape, def: ListDef) -> Self {
Self { data, shape, def }
}
#[inline(always)]
pub fn shape(&self) -> &'static Shape {
self.shape
}
#[inline(always)]
fn list_vtable(&self) -> &'static ListVTable {
self.def.vtable
}
pub unsafe fn push(&mut self, item: Opaque<'_>) {
unsafe { (self.list_vtable().push)(self.data, item) }
}
pub fn len(&self) -> usize {
unsafe { (self.list_vtable().len)(self.data.as_const()) }
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn get_item_ptr(&self, index: usize) -> OpaqueConst {
unsafe { (self.list_vtable().get_item_ptr)(self.data.as_const(), index) }
}
pub fn build_in_place(self) -> Opaque<'mem> {
self.data
}
pub fn def(&self) -> &ListDef {
&self.def
}
}