use facet_core::{Facet, Opaque, OpaqueConst, OpaqueUninit, Shape, TryFromError, ValueVTable};
use facet_peek::Peek;
pub struct TypedPokeValueUninit<'mem, T: Facet> {
poke_value: PokeValueUninit<'mem>,
_phantom: core::marker::PhantomData<T>,
}
impl<'mem, T: Facet> TypedPokeValueUninit<'mem, T> {
fn new(poke_value: PokeValueUninit<'mem>) -> Self {
Self {
poke_value,
_phantom: core::marker::PhantomData,
}
}
pub fn put(self, value: T) -> PokeValue<'mem> {
let data = unsafe { self.poke_value.data.put(value) };
unsafe { PokeValue::new(data, self.poke_value.shape) }
}
}
pub struct PokeValueUninit<'mem> {
data: OpaqueUninit<'mem>,
shape: &'static Shape,
}
impl core::fmt::Debug for PokeValueUninit<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("PokeValue")
.field("shape", &self.shape)
.finish_non_exhaustive()
}
}
impl<'mem> PokeValueUninit<'mem> {
#[inline(always)]
pub fn into_value(self) -> Self {
self
}
pub fn typed<T: Facet>(self) -> Result<TypedPokeValueUninit<'mem, T>, Self> {
if self.shape.is_type::<T>() {
Ok(TypedPokeValueUninit::new(self))
} else {
Err(self)
}
}
#[inline(always)]
pub fn shape(&self) -> &'static Shape {
self.shape
}
pub(crate) unsafe fn new(data: OpaqueUninit<'mem>, shape: &'static Shape) -> Self {
Self { data, shape }
}
#[inline(always)]
fn vtable(&self) -> &'static ValueVTable {
self.shape.vtable
}
pub unsafe fn data(&mut self) -> OpaqueUninit<'mem> {
self.data
}
pub fn try_from<'src>(
self,
source: OpaqueConst<'src>,
) -> Result<Opaque<'mem>, (Self, TryFromError)> {
if let Some(try_from_fn) = self.vtable().try_from {
match unsafe { try_from_fn(source, self.data) } {
Ok(built_val) => Ok(built_val),
Err(err) => Err((self, err)),
}
} else {
let shape = self.shape;
Err((self, TryFromError::Unimplemented(shape)))
}
}
pub fn parse(self, s: &str) -> Result<Opaque<'mem>, Self> {
if let Some(parse_fn) = self.vtable().parse {
match unsafe { parse_fn(s, self.data) } {
Ok(parsed_val) => Ok(parsed_val),
Err(_) => Err(self),
}
} else {
Err(self)
}
}
pub fn put<'src, T>(self, value: T) -> Opaque<'mem>
where
T: Facet + 'src,
{
self.shape.assert_type::<T>();
unsafe { self.data.put(value) }
}
pub fn default_in_place(self) -> Result<Opaque<'mem>, Self> {
if let Some(default_in_place_fn) = self.vtable().default_in_place {
let default_val = unsafe { default_in_place_fn(self.data) };
Ok(default_val)
} else {
Err(self)
}
}
pub fn clone_from<'src>(self, source: Peek<'src>) -> Result<Peek<'mem>, Self> {
if let Some(clone_fn) = self.vtable().clone_into {
let cloned_val = unsafe { clone_fn(source.data(), self.data) };
Ok(unsafe { Peek::unchecked_new(cloned_val.as_const(), self.shape) })
} else {
Err(self)
}
}
}
pub struct TypedPokeValue<'mem, T: Facet> {
poke_value: PokeValue<'mem>,
_phantom: core::marker::PhantomData<T>,
}
impl<'mem, T: Facet> TypedPokeValue<'mem, T> {
fn new(poke_value: PokeValue<'mem>) -> Self {
Self {
poke_value,
_phantom: core::marker::PhantomData,
}
}
pub fn replace(self, value: T) -> Opaque<'mem> {
unsafe { self.poke_value.data.replace(value) }
}
}
pub struct PokeValue<'mem> {
data: Opaque<'mem>,
shape: &'static Shape,
}
impl core::fmt::Debug for PokeValue<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("PokeValue")
.field("shape", &self.shape)
.field("data", &self.as_peek())
.finish()
}
}
impl<'mem> PokeValue<'mem> {
#[inline(always)]
pub fn into_value(self) -> Self {
self
}
pub fn typed<T: Facet>(self) -> Result<TypedPokeValue<'mem, T>, Self> {
if self.shape.is_type::<T>() {
Ok(TypedPokeValue::new(self))
} else {
Err(self)
}
}
#[inline(always)]
pub fn shape(&self) -> &'static Shape {
self.shape
}
pub(crate) unsafe fn new(data: Opaque<'mem>, shape: &'static Shape) -> Self {
Self { data, shape }
}
#[inline(always)]
fn vtable(&self) -> &'static ValueVTable {
self.shape.vtable
}
pub fn as_peek(&self) -> Peek<'_> {
unsafe { Peek::unchecked_new(self.data.as_const(), self.shape) }
}
pub unsafe fn data(&mut self) -> Opaque<'mem> {
self.data
}
pub fn replace<'src, T>(self, value: T) -> Opaque<'mem>
where
T: Facet + 'src,
{
self.shape.assert_type::<T>();
unsafe { self.data.replace(value) }
}
pub fn debug_fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
if let Some(debug_fn) = self.vtable().debug {
unsafe { debug_fn(self.data.as_const(), f) }
} else {
f.write_str("<no debug impl>")
}
}
pub fn display_fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
if let Some(display_fn) = self.vtable().display {
unsafe { display_fn(self.data.as_const(), f) }
} else {
f.write_str("<no display impl>")
}
}
}