tagged-box 0.1.1

An implementation of Box that uses tagged pointers
Documentation
//! 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