1个不稳定版本
0.1.0 | 2024年3月25日 |
---|
#11 在 #named-fields
在 array-as-struct 中使用
17KB
264 行
Array As Struct
一个用于在数组类型上实现人体工程学“字段”访问的crate。
动机
有时你正在处理接受切片或数组的API,但你的代码更希望使用命名字段。一个例子可能是一个接受 [u8; 3]
颜色的API,但你更希望有
struct Color{ r: u8, g: u8, b: u8 }
一个解决方案是使用 repr(C)
和 transmute
或一个 union
,但这显然排除了 forbid(unsafe_code)
。
一个更安全的选择是使用枚举来表示每个字段,这可以通过像 enum-map
这样的crate来实现。这要好得多,但涉及到使用宏来构建类型,有时索引操作和枚举变体解析会阻碍代码的可读性。
use enum_map::{EnumMap, Enum};
#[derive(Debug, Enum)]
enum ColorType {
R,
G,
B,
}
type Color = EnumMap<ColorType, u8>;
let mut color: Color = enum_map! {
Example::R => 247,
Example::G => 0,
Example::B => 0,
};
color[Example::G] = 76;
这个crate提供了一个替代方法,依赖于辅助结构体在数组类型和基于字段的结构体类型之间架起桥梁。
use array_as_struct::{array_as_struct, ArrayStruct};
#[array_as_struct]
// Despite this declaration, `Color` is actual a tuple struct
// which looks like `struct Color([u8; 3]);`
pub struct Color {
r: u8,
g: u8,
b: u8,
}
// This is the actual named-field struct
type ColorValue = <Color as ArrayStruct>::Value;
let mut color = Color::from_val(ColorValue { r: 247, g: 0, b: 0 });
*f.muts().g = 76;
常见问题解答
- 为什么用基于数组的元组结构体替换原始声明?为什么不直接添加一个由 derive 生成的数组结构体类型?
这个crate的主要动机是帮助人们处理 [T]
API。通过隐藏原始基于字段的结构体,这个crate使基于数组的类型成为默认类型,鼓励用户将基于字段的结构体纯粹视为一个短暂的、人体工程学的工具,用于通过名称引用“字段”。
依赖项
~1.9–2.5MB
~51K SLoC