#枚举 #集合 #哈希表 #枚举哈希表

enum-collections

针对枚举优化且支持运行时初始化的集合数据结构

16个版本 (6个稳定版)

1.5.0 2024年5月26日
0.10.0 2024年2月19日
0.7.0 2023年2月6日
0.4.0 2022年12月30日

#240数据结构

Download history 302/week @ 2024-05-10 58/week @ 2024-05-17 861/week @ 2024-05-24 41/week @ 2024-05-31 16/week @ 2024-06-07 1/week @ 2024-06-14 3/week @ 2024-06-28 17/week @ 2024-07-05 84/week @ 2024-07-26 11/week @ 2024-08-02

95 每月下载

Apache-2.0

32KB
284

EnumMap for Rust

Rust Crates.io docs.rs

贡献指南 | Apache v2 许可证

枚举变体到值的映射。EnumMap 是一个固定大小的映射,其中每个枚举变体映射到一个值。此 EnumMap 实现使用 安全 Rust 且作为数组(固定大小)的抽象,数组的索引对应于枚举变体的位置。

因为它是数组的包装,所以默认情况下是堆栈分配的。简单地通过 std::boxed::Box 调用它将使其移动到堆上,由调用者决定。

  • 通过枚举变体索引。
  • 通过枚举变体索引。
  • 如果枚举是 Debug,则进行调试。
  • 如果值是 PartialEq,则进行 PartialEq。对于 Eq 也是如此。

Debug 和 Eq 是可选功能。默认情况下是启用的。

用法

请参阅 文档 以获取功能列表和更深入的文档。

use enum_collections::{EnumMap, Enumerated, em, em_default, em_option};

#[derive(Enumerated)]
pub enum Letter {
   A,
   B,
}

// Indexing and mutation
// The SIZE hint is required until [generic_const_expr](https://github.com/rust-lang/rust/issues/76560) are stabilized.
let mut enum_map = EnumMap::<Letter, i32, { Letter::SIZE }>::new_default();
assert_eq!(0, enum_map[Letter::A]);
enum_map[Letter::A] = 42;
assert_eq!(42, enum_map[Letter::A]);

// Construction using macros
// (Key type, Value type, Key=>Value pairs)
let enum_map = em!(Letter, i32,  A=>42, B=>24); // All values set explicitly
assert_eq!(42, enum_map[Letter::A]);
assert_eq!(24, enum_map[Letter::B]);

// (Key type, Value type, optional Key=>Value pairs)
let enum_map = em_default!(Letter, i32, A => 42); // Default used for missing values
assert_eq!(42, enum_map[Letter::A]);
assert_eq!(i32::default(), enum_map[Letter::B]);

let enum_map = em_default!(Letter, i32,); // All default
assert_eq!(i32::default(), enum_map[Letter::A]);
assert_eq!(i32::default(), enum_map[Letter::B]);

// EnumMap of optional values `Option<V>`, value type is automatically wrapped in `Option`.
// (Key type, Value type, optional Key=>Value pairs)
let enum_map = em_option!(Letter, i32, A => 42);
assert_eq!(Some(42), enum_map[Letter::A]);
assert_eq!(None, enum_map[Letter::B]);

// Constructor with default values
let enum_map_default = EnumMap::<Letter, i32, { Letter::SIZE }>::new_default();
assert_eq!(0, enum_map_default[Letter::A]);
assert_eq!(0, enum_map_default[Letter::B]);

// Convenience constructor for optional values
let mut enum_map_option = EnumMap::<Letter, Option<i32>, { Letter::SIZE }>::new_option();
assert_eq!(None, enum_map_option[Letter::A]);
assert_eq!(None, enum_map_option[Letter::B]);
enum_map_option[Letter::A] = Some(42);
assert_eq!(Some(42), enum_map_option[Letter::A]);

// Constructor with custom initialization
#[derive(PartialEq, Eq, Debug)]
struct Custom;
let enum_map = EnumMap::<Letter, Custom, { Letter::SIZE }>::new(|| Custom);
assert_eq!(Custom, enum_map[Letter::A]);
assert_eq!(Custom, enum_map[Letter::B]);

// Custom initialization function with enum variant (key) inspection
let enum_map = EnumMap::<Letter, i32, { Letter::SIZE }>::new_inspect(|letter| {
   match letter {
      Letter::A => 42,
      Letter::B => 24,
   }
});
assert_eq!(42, enum_map[Letter::A]);
assert_eq!(24, enum_map[Letter::B]);

// Debug
#[derive(Enumerated, Debug)]
pub enum LetterDebugDerived {
   A,
   B,
}
let enum_map_debug =
    EnumMap::<LetterDebugDerived, i32, { LetterDebugDerived::SIZE }>::new(|| 42);
assert_eq!("{A: 42, B: 42}", format!("{:?}", enum_map_debug));

迭代枚举变体

#[derive(Enumerated, Debug)]
pub enum Letter {
   A,
   B,
}

Letter::VARIANTS
    .iter()
    .for_each(|letter| println!("{:?}", letter));

功能

功能部分是功能标志的,但默认启用。这是为了在不需要时关闭此功能,例如 DebugEq 实现。有关详细信息,请参阅 docs.rs

基准测试

使用 cargo bench 运行基准测试。虽然 EnumMap 在皮秒内运行,但 std::collections::HashMap 在 10 纳秒以上。

基准测试结果
EnumMap get             time:   [221.09 ps 221.59 ps 222.21 ps]
Found 10 outliers among 100 measurements (10.00%)
  5 (5.00%) high mild
  5 (5.00%) high severe

EnumMap insert          time:   [230.05 ps 233.38 ps 236.25 ps]
Found 2 outliers among 100 measurements (2.00%)
  1 (1.00%) high mild
  1 (1.00%) high severe

EnumMap new: default    time:   [852.31 ps 853.28 ps 854.37 ps]
Found 2 outliers among 100 measurements (2.00%)
  1 (1.00%) low mild
  1 (1.00%) high mild

EnumMap new: Option::None
                        time:   [1.7100 ns 1.7110 ns 1.7120 ns]
Found 2 outliers among 100 measurements (2.00%)
  1 (1.00%) high mild
  1 (1.00%) high severe

EnumMap new: provider fn
                        time:   [791.17 ps 792.38 ps 793.65 ps]
Found 7 outliers among 100 measurements (7.00%)
  1 (1.00%) low mild
  4 (4.00%) high mild
  2 (2.00%) high severe

EnumMap new: inspecting provider fn
                        time:   [775.03 ps 776.84 ps 778.92 ps]
Found 8 outliers among 100 measurements (8.00%)
  4 (4.00%) high mild
  4 (4.00%) high severe

std::collections::HashMap get
                        time:   [13.433 ns 13.484 ns 13.543 ns]
Found 8 outliers among 100 measurements (8.00%)
  3 (3.00%) high mild
  5 (5.00%) high severe

std::collections::HashMap insert
                        time:   [14.094 ns 14.107 ns 14.121 ns]
Found 4 outliers among 100 measurements (4.00%)
  1 (1.00%) high mild
  3 (3.00%) high severe

依赖关系

~1.5MB
~34K SLoC