use crate::{
enums::IsVariant,
field::{
DropFields, FieldType, GetField, GetFieldMut, GetFieldRawMutFn, GetVariantField,
GetVariantFieldMut, IntoField, IntoVariantField, MovedOutFields, SpecGetFieldMut,
},
path::{IsTStr, TStr, VariantField},
};
use std_::{
fmt::{self, Debug},
marker::PhantomData,
mem::ManuallyDrop,
ops::Deref,
};
#[derive(Copy, Clone, PartialEq, PartialOrd, Ord, Eq)]
pub struct VariantProxy<T: ?Sized, V> {
_marker: PhantomData<V>,
value: T,
}
impl<T: ?Sized, V> VariantProxy<T, TStr<V>> {
#[inline(always)]
pub const unsafe fn new(value: T, name: TStr<V>) -> Self
where
T: Sized,
{
let _ = ManuallyDrop::new(name);
Self {
value,
_marker: PhantomData,
}
}
#[inline(always)]
pub unsafe fn from_ref(reference: &T, _: TStr<V>) -> &Self {
&*(reference as *const T as *const VariantProxy<T, TStr<V>>)
}
#[inline(always)]
pub unsafe fn from_mut(reference: &mut T, vari: TStr<V>) -> &mut Self {
&mut *Self::from_raw_mut(reference, vari)
}
#[inline(always)]
pub const unsafe fn from_raw_mut(ptr: *mut T, name: TStr<V>) -> *mut Self {
let _ = ManuallyDrop::new(name);
ptr as *mut VariantProxy<T, TStr<V>>
}
#[inline(always)]
pub fn get(&self) -> &T {
&self.value
}
pub unsafe fn get_mut(&mut self) -> &mut T {
&mut self.value
}
pub fn into_inner(self) -> T
where
T: Sized,
{
self.value
}
#[allow(clippy::wrong_self_convention)]
pub unsafe fn as_raw_mut(this: *mut Self) -> *mut T {
this as *mut T
}
}
impl<T: ?Sized, V> Deref for VariantProxy<T, V>
where
V: IsTStr,
{
type Target = T;
#[inline(always)]
fn deref(&self) -> &T {
&self.value
}
}
impl<T, V> Debug for VariantProxy<T, V>
where
T: ?Sized + Debug,
V: IsTStr,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("VariantProxy")
.field("value", &&self.value)
.finish()
}
}
impl<T, V, F> FieldType<F> for VariantProxy<T, V>
where
T: ?Sized + FieldType<VariantField<V, F>>,
V: IsTStr,
{
type Ty = T::Ty;
}
impl<T, V, F> GetField<F> for VariantProxy<T, V>
where
T: ?Sized + GetVariantField<V, F>,
V: IsTStr,
{
#[inline(always)]
fn get_field_(&self, fname: F) -> &T::Ty {
unsafe { self.value.get_vfield_unchecked(V::DEFAULT, fname) }
}
}
unsafe impl<T, V, F> GetFieldMut<F> for VariantProxy<T, V>
where
T: ?Sized + GetVariantFieldMut<V, F>,
V: IsTStr,
{
#[inline(always)]
fn get_field_mut_(&mut self, fname: F) -> &mut T::Ty {
unsafe { self.value.get_vfield_mut_unchecked(V::DEFAULT, fname) }
}
#[inline(always)]
unsafe fn get_field_raw_mut(this: *mut (), fname: F) -> *mut T::Ty
where
Self: Sized,
{
<Self as SpecGetFieldMut<F>>::get_field_raw_mut_inner(this, fname)
}
#[inline(always)]
fn get_field_raw_mut_fn(&self) -> GetFieldRawMutFn<F, T::Ty> {
(**self).get_vfield_raw_mut_unchecked_fn()
}
}
unsafe impl<T, V, F> SpecGetFieldMut<F> for VariantProxy<T, V>
where
T: ?Sized + GetVariantFieldMut<V, F>,
V: IsTStr,
{
default_if! {
#[inline(always)]
cfg(feature="specialization")
unsafe fn get_field_raw_mut_inner(
this: *mut (),
fname: F,
) -> *mut T::Ty
where
Self: Sized
{
let func=(**(this as *mut Self)).get_vfield_raw_mut_unchecked_fn();
func(
this,
fname,
)
}
}
}
#[cfg(feature = "specialization")]
unsafe impl<T, V, F> SpecGetFieldMut<F> for VariantProxy<T, V>
where
T: GetVariantFieldMut<V, F>,
V: IsTStr,
{
unsafe fn get_field_raw_mut_inner(this: *mut (), fname: F) -> *mut T::Ty {
T::get_vfield_raw_mut_unchecked(this, fname)
}
}
unsafe impl<T, V, F> IntoField<F> for VariantProxy<T, V>
where
T: IntoVariantField<V, F>,
V: IsTStr,
{
#[inline(always)]
fn into_field_(self, fname: F) -> T::Ty
where
Self: Sized,
{
unsafe { self.value.into_vfield_unchecked_(V::DEFAULT, fname) }
}
#[inline(always)]
unsafe fn move_out_field_(&mut self, fname: F, moved: &mut MovedOutFields) -> T::Ty
where
Self: Sized,
{
self.value
.move_out_vfield_unchecked_(V::DEFAULT, fname, moved)
}
}
unsafe impl<T, V> DropFields for VariantProxy<T, V>
where
T: IsVariant<V> + DropFields,
V: IsTStr,
{
fn pre_move(&mut self) {
let mut this = crate::utils::RunOnDrop::new(
&mut self.value,
#[inline(always)]
|this| {
if !this.is_variant_(V::DEFAULT) {
abort!(
"\n\n\n\
The enum changed the active variant in `<{} as DropFields>::pre_move`\
\n\n\n",
std_::any::type_name::<Self>(),
);
}
},
);
<T as DropFields>::pre_move(this.reborrow_mut());
}
unsafe fn drop_fields(&mut self, moved: MovedOutFields) {
<T as DropFields>::drop_fields(&mut self.value, moved)
}
}