When writing systems software—especially virtual machine monitors (VMMs) like Alioth, operating systems, or drivers—you inevitably find yourself swimming in a sea of magic numbers. Hardware registers, hypercall ABIs, and binary file formats define strict integer values for their constants.
In Rust, the traditional enum is fantastic for exhaustive pattern matching, but it falls short when dealing with external interfaces. Why? Because an external source (like a guest OS or a hardware device) might send you a value that your enum doesn’t know about. If you use unsafe to cast an unknown integer into a standard Rust enum, you trigger undefined behavior.
To solve this, systems programmers often use the “newtype” pattern combined with associated constants. In the Alioth project—a virtualization hypervisor written in Rust—this pattern is beautifully abstracted away into a single, powerful declarative macro: consts!.
In this post, we’ll dive into how the consts! macro works, why it’s designed this way, and the immense benefits it brings to systems programming in Rust.
The consts! Macro
Here is the core definition of the macro from alioth/src/utils/utils.rs:
#[macro_export]
macro_rules! consts {
(
$(#[$attr:meta])*
$vs:vis struct $EnumName:ident($TyName:ty) {
$( $(#[$vattr:meta])* $VARIANT:ident = $value:expr;)*
}
) => {
#[repr(transparent)]
#[derive(PartialEq, Eq, Copy, Clone)]
$(#[$attr])*
$vs struct $EnumName($TyName);
impl $EnumName {
$($(#[$vattr])* pub const $VARIANT: $EnumName = $EnumName($value);)*
#[allow(dead_code)]
pub const fn raw(self) -> $TyName {
self.0
}
#[allow(dead_code)]
pub const fn name(self) -> &'static str {
match self {
$($EnumName::$VARIANT => stringify!($VARIANT),)*
#[allow(unreachable_patterns)]
_ => "Unknown"
}
}
}
/* ... Custom Debug & From impls ... */
}
}
This macro takes a syntax that looks like a C-style struct/enum and expands it into a fully-featured Rust “newtype” struct.
How It’s Used
In Alioth, you’ll find this macro used everywhere—from ARM PSCI (Power State Coordination Interface) function IDs to QCOW2 compression types and FUSE filesystem opcodes.
Here is an example of defining PSCI function IDs from alioth/src/arch/aarch64/psci.rs:
consts! {
/// https://developer.arm.com/documentation/den0022/latest/
pub struct PsciFunc(u32) {
PSCI_VERSION = 0x8400_0000;
CPU_SUSPEND_32 = 0x8400_0001;
CPU_SUSPEND_64 = 0xc400_0001;
CPU_OFF = 0x8400_0002;
// ... more constants
}
}
The Benefits of consts!
1. Open and Extensible by Design
Unlike Rust’s standard enum, the underlying storage is explicitly defined as a raw integer (e.g., u32). This means you can safely construct a PsciFunc from any u32 value without causing Undefined Behavior. If a guest OS sends an unknown or reserved PSCI function ID, the VMM can safely receive it, realize it doesn’t match known constants, and return a “Not Supported” error rather than crashing or panicking.
2. Type Safety
By wrapping the raw integer in a new struct, consts! prevents accidental mixing of different domains of constants. You can’t accidentally pass a FuseOpcode to a function expecting a PsciFunc, even if they are fundamentally both u32 under the hood. The compiler guarantees domain correctness.
3. Transparent FFI and Zero-Copy Serialization
Notice the #[repr(transparent)] attribute injected by the macro. This guarantees to the compiler that the memory layout of PsciFunc is exactly identical to a bare u32.
Furthermore, the macro allows passing through custom derive macros. In Alioth, it is frequently combined with crates like zerocopy for zero-allocation binary parsing:
consts! {
#[derive(FromBytes, Immutable, IntoBytes)]
pub struct FuseOpcode(u32) {
LOOKUP = 1;
FORGET = 2;
GETATTR = 3;
// ...
}
}
Thanks to #[repr(transparent)] and FromBytes, Alioth can cast a raw byte slice fetched from a FUSE socket directly into a strongly-typed FuseOpcode safely.
4. Excellent Developer Ergonomics
The macro generates highly useful boilerplate automatically:
raw(): Easily extract the underlying primitive.FromTrait Impls: Convert seamlessly between the raw integer and the newtype using.into().- Human-Readable Formatting: The generated
Debugimplementation provides a fantastic developer experience. If the value matches a known constant, it prints beautifully (e.g.,PsciFunc::CPU_OFF). If it’s an unknown value (like0x9999_9999), it falls back to printing the raw wrapped dataPsciFunc(2576980377). This makes logs significantly easier to read and debug compared to a stream of raw hexadecimal numbers.
Conclusion
The consts! macro is a quintessential example of Rust’s declarative macros solving real-world systems programming problems. By automating the “newtype” pattern, it gives Alioth the type safety and developer ergonomics of Rust enums, without sacrificing the ABI guarantees and “open” nature required to interface with raw hardware, external protocols, and untrusted guest environments.