pub unsafe trait Phenotype {
type Value;
const NUM_VARIANTS: usize;
const BITS: usize;
const PEAPOD_SIZE: Option<usize>;
const IS_MORE_COMPACT: Option<bool>;
fn cleave(self) -> (usize, Self::Value);
unsafe fn reknit(tag: usize, value: Self::Value) -> Self;
}
Expand description
This trait represents the behavior of an enum
/tagged union.
Note: it should only be implemented with #[derive(Phenotype)]
Safety
This trait is marked unsafe because extreme care must be taken to implement
it correctly. In particular, the reknit
method can cause undefined behavior
if called with invalid inputs. Manual implementation of the trait is heavily
discouraged, but there may be cases (e.g. const
generics) where it is necessary.
Required Associated Types
Required Associated Constants
sourceconst NUM_VARIANTS: usize
const NUM_VARIANTS: usize
The number of variants of the enum.
The number of bits needed to represent every variant of the enum. For example, if the enum has 4 variants, then two bits are needed.
sourceconst PEAPOD_SIZE: Option<usize>
const PEAPOD_SIZE: Option<usize>
The number of bits Phenotype
uses to represent and instance of a type.
If the type Phenotype
is being implemented for is generic,
this will be None
, as sizes may vary accross different
generic parameters. For example, Type<usize>
could be differently
sized than Type<[usize; 4]>
sourceconst IS_MORE_COMPACT: Option<bool>
const IS_MORE_COMPACT: Option<bool>
Whether using Phenotype
produces a more compact representation.
Will be Some(true)
if implementations are the same size.
If the type Phenotype
is being implemented for is generic,
this will be None
, as sizes may vary accross different
generic parameters. For example, Type<usize>
could be differently
sized than Type<[usize; 4]>
Required Methods
Takes an enum variant and cleave
s it into a two parts:
a tag, and an union representing the data the enum can hold.
If the enum variant doesn’t hold data, None
is returned as
the second tuple element.
Note: if the results of a call to cleave
are not eventually
reknit
ed, the destructor for the cleave
ed enum will not run.
This can cause memory leaks. Types that manage heap memory often
implement cleanup and deallocation in their Drop
implementations.
Takes a tag and a value and recombines them into a proper instance of an enum variant.
Safety
Calling this function with incorrect inputs can result in undefined behavior. The tag must always match the state that the union is in.
For example, consider the following example
#[derive(Phenotype)]
enum UB {
U(usize), // -> tag = 0
B(bool) // -> tag = 1
}
// This is the type <UB as Phenotype>::Value
union Value {
U: usize,
B: bool
}
use peapod::Phenotype;
fn main {
let ub = UB::U(3);
let (_, data) = ub.cleave();
// ** DANGER **
// We are interpreting 3 as a bool! That's undefined behavior.
let BAD = <UB as Phenotype>::reknit(1, data);
}