//! A guide to manually implementing a tagged enum
//!
//! A good start is by looking at the code generated by [`tagged_box!`]. Given the following macro invocation:
//!
//! ```rust
//! # use tagged_box::tagged_box;
//! #
//! tagged_box! {
//! struct Container, enum Item {
//! Integer(i32),
//! Boolean(bool),
//! }
//! }
//! ```
//!
//! This code will be generated:
//!
//! ```rust
//! # use tagged_box::{TaggedBox, TaggableContainer, TaggableInner};
//! # use core::mem::ManuallyDrop;
//! #
//! #[repr(transparent)]
//! struct Container {
//! value: TaggedBox<Item>,
//! }
//!
//! impl TaggableContainer for Container {
//! type Inner = Item;
//!
//! fn into_inner(self) -> Self::Inner {
//! enum EnumCounter {
//! Integer,
//! Boolean,
//! }
//!
//! unsafe {
//! match self.value.discriminant() {
//! discrim if discrim == EnumCounter::Integer as _ =>
//! Item::Integer(TaggedBox::into_inner(self.value)),
//! discrim if discrim == EnumCounter::Boolean as _ =>
//! Item::Boolean(TaggedBox::into_inner(self.value)),
//! _ => panic!(),
//! }
//! }
//! }
//! }
//!
//! enum Item {
//! Integer(i32),
//! Boolean(bool),
//! }
//!
//! impl TaggableInner for Item {
//! fn into_tagged_box(self) -> TaggedBox<Self> {
//! enum EnumCounter {
//! Integer,
//! Boolean,
//! }
//!
//! match self {
//! Self::Integer(value) => TaggedBox::new(value, EnumCounter::Integer as _),
//! Self::Boolean(value) => TaggedBox::new(value, EnumCounter::Boolean as _),
//! }
//! }
//!
//! fn from_tagged_box(tagged: TaggedBox<Self>) -> Self {
//! enum EnumCounter {
//! Integer,
//! Boolean,
//! }
//!
//! unsafe {
//! match tagged.discriminant() {
//! discrim if discrim == EnumCounter::Integer as _ =>
//! Self::Integer(TaggedBox::into_inner(tagged)),
//! discrim if discrim == EnumCounter::Boolean as _ =>
//! Self::Boolean(TaggedBox::into_inner(tagged)),
//! _ => panic!(),
//! }
//! }
//! }
//!
//! unsafe fn ref_from_tagged_box<F>(tagged: &TaggedBox<Self>, callback: F)
//! where
//! F: FnOnce(&Self),
//! {
//! enum EnumCounter {
//! Integer,
//! Boolean,
//! }
//!
//! unsafe {
//! match tagged.discriminant() {
//! discrim if discrim == EnumCounter::Integer as _ => {
//! let variant = ManuallyDrop::new(Self::Integer(tagged.as_ptr::<i32>().read()));
//! (callback)(&variant)
//! }
//! discrim if discrim == EnumCounter::Boolean as _ => {
//! let variant = ManuallyDrop::new(Self::Boolean(tagged.as_ptr::<bool>().read()));
//! (callback)(&variant)
//! }
//! _ => panic!(),
//! }
//! }
//! }
//! }
//! ```
//!
//! This is a lot of code, so we'll break it down a bit.
//! The first piece of code generated is this struct:
//!
//! ```rust
//! # use tagged_box::{TaggedBox, TaggableContainer, TaggableInner};
//! # enum Item {}
//! #
//! #[repr(transparent)]
//! struct Container {
//! value: TaggedBox<Item>,
//! }
//! ```
//!
//! This is the 'handle' if you will. It allows you to generically hold multiple different instances
//! of the same overarching enum that have different internal types. It's essentially an enum and a
//! [`Box`] rolled into one. However, unlike leaving the safety guarantees up to you, the `tagged_box!`
//! macro creates a default implementation that makes sure that everything goes smoothly.
//!
//! Next is the implementation of [`TaggableContainer`] for `Container`, which is the safe interface for
//! retrieving the correct variant of the enum from the backing `TaggedBox`.
//!
//! Then we have the `Item` enum, which is a representation of what the `TaggedBox` is holding, and can be conveniently
//! gotten from any `Container` instance. This has the [`TaggableInner`] trait implemented on it, which allows us to
//! have convenient things like `Clone`, `PartialEq` and `Ord`.
//!
//! [`tagged_box!`]: ../macro.tagged_box.html
//! [`Box`]: https://doc.rust-lang.org/alloc/boxed/struct.Box.html
//! [`TaggableContainer`]: crate::TaggableContainer
//! [`TaggableInner`]: crate::TaggableInner