#[cfg(no_std)]
use core::{
any::Any,
fmt::Debug,
mem::{ManuallyDrop, MaybeUninit},
};
use crate::{argument::VariantHandle,argument::discriminant::Discriminant, OwnedArgument};
#[cfg(not(no_std))]
use std::{
any::Any,
fmt::Debug,
mem::{ManuallyDrop, MaybeUninit}
};
#[derive(Debug)]
pub enum ArgumentKind<'a>
{
Borrowed(&'a dyn Any),
Owned(OwnedArgument)
}
pub(super) enum RawArgument<'a>
{
Borrowed(&'a dyn VariantHandle),
Owned(OwnedArgument)
}
pub(super) union InnerArgument<'a>
{
owned: ManuallyDrop<OwnedArgument>,
ref_: &'a dyn VariantHandle
}
impl InnerArgument<'_>
{
#[inline(always)]
pub fn new_owned(item: OwnedArgument) -> Self
{
let owned = ManuallyDrop::new(item);
Self
{
owned
}
}
#[inline(always)]
pub fn discriminant(&self) -> Discriminant
{
unsafe
{
self.owned
.discriminant()
}
}
#[inline(always)]
pub fn is_owned(&self) -> bool
{
matches!(self.discriminant(), Discriminant::Inlined | Discriminant::Allocated )
}
#[inline(always)]
pub fn is_borrowed(&self) -> bool
{
matches!(self.discriminant(), Discriminant::Borrowed)
}
#[inline(always)]
pub fn to_mut(&mut self) -> &mut dyn Any
{
match self.discriminant()
{
Discriminant::Borrowed =>
{
let owned : OwnedArgument =
unsafe
{
self.ref_.clone_object()
};
*self = InnerArgument::new_owned(owned);
match self.discriminant()
{
Discriminant::Inlined | Discriminant::Allocated =>
unsafe
{
&mut *self.owned
},
_ => unreachable!()
}
}
_ =>
unsafe
{
&mut *self.owned
}
}
}
#[inline(always)]
pub unsafe fn owned_debug_handle(&self) -> &dyn Debug
{
unsafe
{
&*self.owned
}
}
}
impl<'a> InnerArgument<'a>
{
#[inline(always)]
pub fn new_ref(ref_: &'a dyn VariantHandle) -> Self
{
let mut output : Self = unsafe { MaybeUninit::zeroed().assume_init() };
output.ref_ = ref_;
output
}
#[inline(always)]
pub fn as_ref(&'a self) -> Self
{
let ref_ =
match self.discriminant()
{
Discriminant::Borrowed => unsafe { self.ref_unchecked() },
_ => unsafe { self.owned.raw_ref() }
};
Self::new_ref(ref_)
}
#[must_use = "Potential memory leak."]
#[inline(always)]
pub unsafe fn take_raw_argument(&mut self) -> RawArgument<'a>
{
match self.discriminant()
{
Discriminant::Borrowed =>
{
let ref_ = unsafe { self.ref_unchecked() };
RawArgument::Borrowed(ref_)
}
_ =>
{
let owned =
unsafe
{
ManuallyDrop::take(&mut self.owned)
};
RawArgument::Owned(owned)
}
}
}
#[inline(always)]
pub fn into_inner(self) -> ArgumentKind<'a>
{
match self.discriminant()
{
Discriminant::Borrowed => ArgumentKind::Borrowed(unsafe { self.ref_unchecked() }),
_ => ArgumentKind::Owned(ManuallyDrop::into_inner(unsafe { self.owned }))
}
}
#[inline(always)]
pub unsafe fn ref_unchecked(&self) -> &'a dyn VariantHandle
{
unsafe
{
self.ref_
}
}
#[inline(always)]
pub fn to_ref(&'a self) -> &'a dyn Any
{
match self.discriminant()
{
Discriminant::Borrowed => unsafe { self.ref_unchecked() },
_ => unsafe { self.owned.raw_ref() }
}
}
}