#[macro_export]
macro_rules! tagged_box {
(
$( #[$meta:meta] )*
$struct_vis:vis struct $struct:ident, $enum_vis:vis enum $enum:ident {
$( $variant:ident($ty:ty), )+
}
) => {
$( #[$meta] )*
#[repr(transparent)]
$struct_vis struct $struct {
value: $crate::TaggedBox<$enum>,
}
impl $crate::TaggableContainer for $struct {
type Inner = $enum;
fn into_inner(self) -> $enum {
#[doc(hidden)]
#[allow(non_camel_case_types)]
enum __tagged_box_enum_counter {
$( $variant ),+
}
unsafe {
match self.value.discriminant() {
$(
discrim if discrim == __tagged_box_enum_counter::$variant as _ =>
$enum::$variant($crate::TaggedBox::into_inner::<$ty>(self.value)),
)+
_ => panic!("Attempted to create an enum variant from a discriminant that doesn't exist!"),
}
}
}
}
impl From<$enum> for $struct {
#[inline]
fn from(variant: $enum) -> Self {
use $crate::TaggableInner;
Self {
value: variant.into_tagged_box(),
}
}
}
$(
impl From<$ty> for $struct {
#[inline]
fn from(value: $ty) -> Self {
use $crate::TaggableInner;
Self {
value: $enum::$variant(value).into_tagged_box(),
}
}
}
)+
$( #[$meta] )*
$enum_vis enum $enum {
$( $variant($ty) ),+
}
impl $crate::TaggableInner for $enum {
fn into_tagged_box(self) -> $crate::TaggedBox<Self> {
#[doc(hidden)]
#[allow(non_camel_case_types)]
enum __tagged_box_enum_counter {
$( $variant ),+
}
match self {
$(
Self::$variant(value) => $crate::TaggedBox::new(value, __tagged_box_enum_counter::$variant as _),
)+
}
}
fn from_tagged_box(tagged: $crate::TaggedBox<$enum>) -> Self {
unsafe {
#[doc(hidden)]
#[allow(non_camel_case_types)]
enum __tagged_box_enum_counter {
$( $variant ),+
}
match tagged.discriminant() {
$(
discrim if discrim == __tagged_box_enum_counter::$variant as _ =>
Self::$variant($crate::TaggedBox::into_inner::<$ty>(tagged)),
)+
discriminant => {
#[allow(non_upper_case_globals)]
const __tagged_box_total_variants: usize = [$( stringify!($variant) ),+].len();
panic!(
"The number of variants in `{}` is {}, but a variant by the discriminant of {} was attempted to be created",
stringify!($enum),
__tagged_box_total_variants,
discriminant
);
}
}
}
}
unsafe fn ref_from_tagged_box<F>(tagged: &$crate::TaggedBox<$enum>, callback: F)
where
F: FnOnce(&$enum),
{
#[doc(hidden)]
#[allow(non_camel_case_types)]
enum __tagged_box_enum_counter {
$( $variant ),+
}
match tagged.discriminant() {
$(
discrim if discrim == __tagged_box_enum_counter::$variant as _ => {
let variant = core::mem::ManuallyDrop::new(Self::$variant(tagged.as_ptr::<$ty>().read()));
(callback)(&variant);
}
)+
discriminant => {
#[allow(non_upper_case_globals)]
const __tagged_box_total_variants: usize = [$( stringify!($variant) ),+].len();
panic!(
"The number of variants in `{}` is {}, but a variant by the discriminant of {} was attempted to be referenced",
stringify!($enum),
__tagged_box_total_variants,
discriminant
);
}
}
}
}
};
}