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

A type that represents all the data an enum can contain. This should be a union whose fields each represent a particular enum variant.

Required Associated Constants

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.

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]>

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 cleaves 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 reknited, the destructor for the cleaveed 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);
}

Implementors