use facet_core::{Facet, FieldError};
use crate::{ReflectError, ReflectErrorKind, peek::TupleType};
use super::Poke;
pub struct PokeTuple<'mem, 'facet> {
pub(crate) value: Poke<'mem, 'facet>,
pub(crate) ty: TupleType,
}
impl<'mem, 'facet> core::fmt::Debug for PokeTuple<'mem, 'facet> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("PokeTuple")
.field("type", &self.ty)
.finish_non_exhaustive()
}
}
impl<'mem, 'facet> PokeTuple<'mem, 'facet> {
fn err(&self, kind: ReflectErrorKind) -> ReflectError {
self.value.err(kind)
}
#[inline]
pub const fn len(&self) -> usize {
self.ty.fields.len()
}
#[inline]
pub const fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline]
pub const fn ty(&self) -> TupleType {
self.ty
}
pub fn field(&self, index: usize) -> Option<crate::Peek<'_, 'facet>> {
let field = self.ty.fields.get(index)?;
let field_ptr = unsafe { self.value.data().field(field.offset) };
Some(unsafe { crate::Peek::unchecked_new(field_ptr, field.shape()) })
}
pub fn field_mut(&mut self, index: usize) -> Result<Poke<'_, 'facet>, ReflectError> {
let field = self.ty.fields.get(index).ok_or_else(|| {
self.err(ReflectErrorKind::FieldError {
shape: self.value.shape,
field_error: FieldError::IndexOutOfBounds {
index,
bound: self.ty.fields.len(),
},
})
})?;
let field_data = unsafe { self.value.data_mut().field(field.offset) };
Ok(unsafe { Poke::from_raw_parts(field_data, field.shape()) })
}
pub fn set_field<T: Facet<'facet>>(
&mut self,
index: usize,
value: T,
) -> Result<(), ReflectError> {
if !self.value.shape.is_pod() {
return Err(self.err(ReflectErrorKind::NotPod {
shape: self.value.shape,
}));
}
let field = self.ty.fields.get(index).ok_or_else(|| {
self.err(ReflectErrorKind::FieldError {
shape: self.value.shape,
field_error: FieldError::IndexOutOfBounds {
index,
bound: self.ty.fields.len(),
},
})
})?;
let field_shape = field.shape();
if field_shape != T::SHAPE {
return Err(self.err(ReflectErrorKind::WrongShape {
expected: field_shape,
actual: T::SHAPE,
}));
}
unsafe {
let field_ptr = self.value.data_mut().field(field.offset);
field_shape.call_drop_in_place(field_ptr);
core::ptr::write(field_ptr.as_mut_byte_ptr() as *mut T, value);
}
Ok(())
}
#[inline]
pub const fn into_inner(self) -> Poke<'mem, 'facet> {
self.value
}
#[inline]
pub fn as_peek_tuple(&self) -> crate::PeekTuple<'_, 'facet> {
crate::PeekTuple {
value: self.value.as_peek(),
ty: self.ty,
}
}
}