Expand description
Unit enums in zero-copy layouts and instruction arguments.
A Rust enum is not Pod: a #[repr(u8)] enum with three variants has
253 byte values that are not a valid value of the type, so overlaying
it on account bytes is undefined behaviour the moment an account holds
one of them. The usual workaround is a bare u8 field and a
hand-written match, which loses the type in the layout and lets a
handler forget the validation.
EnumByte<E> is the field type instead: one byte, alignment 1, every
bit pattern valid as far as memory safety goes, and the enum recovered
through EnumByte::get, which refuses a byte that names no variant.
#[hopper::unit_enum] implements UnitEnum for a fieldless enum, so
the mapping between variants and bytes is generated, not written.
#[hopper::unit_enum]
pub enum Status {
Open = 1,
Settled = 2,
Cancelled = 3,
}
#[hopper::state(disc = 5, version = 1)]
#[derive(Clone, Copy)]
#[repr(C)]
pub struct Order {
pub maker: Address,
pub status: EnumByte<Status>,
}
if order.status.get()? == Status::Open {
order.status.set(Status::Settled);
}Structs§
- Enum
Byte - One byte that stores a
UnitEnum.Pod, so it can sit in a#[hopper::state]layout, a#[hopper::pod]struct, or#[hopper::args]; the enum is validated when it is read.
Traits§
- Unit
Enum - A fieldless enum with a one-byte representation. Implemented by
#[hopper::unit_enum]; hand-written impls must keepfrom_bytethe exact inverse ofto_byteon every variant.