#array #struct #named-fields #field #conversion #no-alloc #derive-debug

no-std array-as-struct

一个用于在数组类型上实现方便的 "字段" 访问的crate

1 个不稳定版本

0.1.0 2024年3月25日

#2459 in Rust 模式

MIT/Apache

10KB

数组作为结构体

一个用于在数组类型上实现方便的 "字段" 访问的crate。

动机

有时你正在处理接收切片或数组的API,但你的代码会更需要一个有命名字段的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。通过隐藏原始基于字段的struct,这个crate使基于数组的类型成为默认类型,鼓励用户将基于字段的struct纯粹作为一个短期的方便工具,通过名称来引用 "字段"。

依赖关系

~1.8–2.5MB
~50K SLoC