我有两个结构体,它们都只需要 7 位来表示自己:
#[repr(transparent)]
struct TypeFlags(u8);
// TypeFlags has capabilities that are invalid for Control
impl std::ops::BitOr for TypeFlags {
type Output = Self;
fn bitor(self, rhs: Self) -> Self::Output {
Self(self.0 | rhs.0)
}
}
#[repr(transparent)]
struct Control(u8);
由于两种类型仅需要 7 位,因此可以创建仅占用一个字节的“任一”类型。
// problem: the compiler sets aside
// a "flag" byte for the enum variant.
// size = 2
enum Either {
Type(TypeFlags),
Ctrl(Control)
}
// problem: pattern matching is painful
struct PackedEither(u8);
是否有我可以利用的枚举的子字节优化,或者我是否必须在像
PackedEither
这样的结构上手动实现位标志?
编译器无法进行该优化,但为了论证起见,我们假设编译器要进行优化,并假设
TypeFlags
存储为 0b0xxx_xxxx
和 Control
存储为 0b1xxx_xxx
。
现在问题来了:
在 Rust 中,我们可以匹配对
Either
的引用并获取对所包含值的引用:
fn unwrap_control_ref(either: &Either) -> &Control {
let Either::Ctrl(control) = some_either_reference else {
panic!("was a `Either::Type`");
};
control
}
现在编译器必须生成引用
Control
值的代码,但是,它不会将其存储在内存中的任何位置,它只存储“Control | 0b1000_0000
”。
遗憾的是,即使我们将
Control
的范围更改为 128..256
并使用标准库内部属性,它也不会像我们想要的那样使用 nieche。