use std::marker::PhantomData;
use std::mem;
use crate::cast;
use crate::private::Private;
use crate::values::FreezeResult;
use crate::values::Freezer;
use crate::values::FrozenHeap;
use crate::values::FrozenValue;
use crate::values::FrozenValueTyped;
use crate::values::Heap;
use crate::values::Tracer;
use crate::values::Value;
use crate::values::layout::avalue::AValue;
use crate::values::layout::avalue::AValueImpl;
use crate::values::layout::avalue::AValueSimpleBound;
use crate::values::layout::avalue::heap_copy_impl;
use crate::values::layout::avalue::heap_freeze_simple_impl;
use crate::values::layout::avalue::try_freeze_directly;
use crate::values::layout::heap::repr::AValueRepr;
pub(crate) fn simple<'v, T: AValueSimpleBound<'v> + 'v>(x: T) -> AValueImpl<'v, AValueSimple<T>> {
assert!(!T::is_special(Private));
AValueImpl::<AValueSimple<T>>::new(x)
}
pub struct AValueSimple<T>(PhantomData<T>);
impl<'v, T: AValueSimpleBound<'v>> AValue<'v> for AValueSimple<T> {
type StarlarkValue = T;
type ExtraElem = ();
fn extra_len(_value: &T) -> usize {
0
}
fn offset_of_extra() -> usize {
mem::size_of::<Self>()
}
unsafe fn heap_freeze(
me: *mut AValueRepr<Self::StarlarkValue>,
freezer: &Freezer,
) -> FreezeResult<FrozenValue> {
unsafe {
if let Some(f) = try_freeze_directly::<Self>(me, freezer) {
return f;
}
heap_freeze_simple_impl::<Self>(me, freezer)
}
}
unsafe fn heap_copy(
me: *mut AValueRepr<Self::StarlarkValue>,
tracer: &Tracer<'v>,
) -> Value<'v> {
unsafe { heap_copy_impl::<Self>(me, tracer, |_v, _tracer| {}) }
}
#[cfg(feature = "pagable")]
fn starlark_serialize(
me: *const AValueRepr<Self::StarlarkValue>,
ctx: &mut dyn crate::pagable::StarlarkSerializeContext,
) -> crate::Result<()> {
let value = unsafe { &(*me).payload };
value.starlark_serialize(ctx)
}
#[cfg(feature = "pagable")]
fn starlark_deserialize(
me: *mut AValueRepr<Self::StarlarkValue>,
ctx: &mut dyn crate::pagable::StarlarkDeserializeContext<'_>,
) -> crate::Result<()> {
let value = T::starlark_deserialize(ctx)?;
unsafe {
std::ptr::write(&mut (*me).payload, value);
}
Ok(())
}
}
impl FrozenHeap {
pub(crate) fn alloc_simple_typed_static<T: AValueSimpleBound<'static> + Send + Sync>(
&self,
val: T,
) -> FrozenValueTyped<'static, T> {
let this: &'static FrozenHeap = unsafe { cast::ptr_lifetime(self) };
this.alloc_raw(simple(val))
}
pub fn alloc_simple_typed<'fv, T: AValueSimpleBound<'fv>>(
&'fv self,
val: T,
) -> FrozenValueTyped<'fv, T> {
self.alloc_raw(simple(val))
}
pub fn alloc_simple<T: AValueSimpleBound<'static> + Send + Sync>(&self, val: T) -> FrozenValue {
self.alloc_simple_typed_static(val).to_frozen_value()
}
}
impl<'v> Heap<'v> {
pub fn alloc_simple<T: AValueSimpleBound<'v> + Send + Sync + 'static>(self, x: T) -> Value<'v> {
self.alloc_raw(simple(x)).to_value()
}
}