#枚举 #序号 #数字 #ordinalize

无 std enum-ordinalize

此库允许枚举不仅能够获取其变体的序号值,还可以从序号值构造枚举。

41 个稳定版本 (3 个主要版本)

4.3.0 2023 年 12 月 15 日
4.2.0 2023 年 11 月 27 日
3.1.15 2023 年 10 月 1 日
3.1.13 2023 年 5 月 10 日
1.0.1 2018 年 9 月 2 日

106Rust 模式 中排名

Download history 102886/week @ 2024-04-06 110175/week @ 2024-04-13 113211/week @ 2024-04-20 106122/week @ 2024-04-27 88985/week @ 2024-05-04 108852/week @ 2024-05-11 95301/week @ 2024-05-18 171806/week @ 2024-05-25 198566/week @ 2024-06-01 192678/week @ 2024-06-08 175830/week @ 2024-06-15 181364/week @ 2024-06-22 184514/week @ 2024-06-29 191806/week @ 2024-07-06 189144/week @ 2024-07-13 159206/week @ 2024-07-20

752,513 每月下载量
用于 683 个包 (直接使用 17 个)

MIT 许可证

19KB

Enum Ordinalize

CI

此库允许枚举不仅能够获取其变体的序号值,还可以从序号值构造枚举。

用法

使用 #[derive(Ordinalize)] 以使枚举(只能有单元变体)实现 Ordinalize 特性。

use enum_ordinalize::Ordinalize;

#[derive(Debug, PartialEq, Eq, Ordinalize)]
enum MyEnum {
    Zero,
    One,
    Two,
}

assert_eq!(3, MyEnum::VARIANT_COUNT);
assert_eq!([MyEnum::Zero, MyEnum::One, MyEnum::Two], MyEnum::VARIANTS);
assert_eq!([0i8, 1i8, 2i8], MyEnum::VALUES);

assert_eq!(0i8, MyEnum::Zero.ordinal());
assert_eq!(1i8, MyEnum::One.ordinal());
assert_eq!(2i8, MyEnum::Two.ordinal());

assert_eq!(Some(MyEnum::Zero), MyEnum::from_ordinal(0i8));
assert_eq!(Some(MyEnum::One), MyEnum::from_ordinal(1i8));
assert_eq!(Some(MyEnum::Two), MyEnum::from_ordinal(2i8));

assert_eq!(MyEnum::Zero, unsafe { MyEnum::from_ordinal_unsafe(0i8) });
assert_eq!(MyEnum::One, unsafe { MyEnum::from_ordinal_unsafe(1i8) });
assert_eq!(MyEnum::Two, unsafe { MyEnum::from_ordinal_unsafe(2i8) });

枚举的大小

序号值是一个整数,其大小由枚举本身决定。枚举的大小随着变体值的幅度增加而增加,无论大小(或负值时更小)。

例如,

use enum_ordinalize::Ordinalize;

#[derive(Debug, PartialEq, Eq, Ordinalize)]
enum MyEnum {
    Zero,
    One,
    Two,
    Thousand = 1000,
}

assert_eq!(4, MyEnum::VARIANT_COUNT);
assert_eq!([MyEnum::Zero, MyEnum::One, MyEnum::Two, MyEnum::Thousand], MyEnum::VARIANTS);
assert_eq!([0i16, 1i16, 2i16, 1000i16], MyEnum::VALUES);

assert_eq!(0i16, MyEnum::Zero.ordinal());
assert_eq!(1i16, MyEnum::One.ordinal());
assert_eq!(2i16, MyEnum::Two.ordinal());

assert_eq!(Some(MyEnum::Zero), MyEnum::from_ordinal(0i16));
assert_eq!(Some(MyEnum::One), MyEnum::from_ordinal(1i16));
assert_eq!(Some(MyEnum::Two), MyEnum::from_ordinal(2i16));

assert_eq!(MyEnum::Zero, unsafe { MyEnum::from_ordinal_unsafe(0i16) });
assert_eq!(MyEnum::One, unsafe { MyEnum::from_ordinal_unsafe(1i16) });
assert_eq!(MyEnum::Two, unsafe { MyEnum::from_ordinal_unsafe(2i16) });

为了适应值 1000MyEnum 的大小会增加。因此,序号用 i16 而不是 i8 表示。

您可以使用 #[repr(type)] 属性来显式控制大小。例如,

use enum_ordinalize::Ordinalize;

#[derive(Debug, PartialEq, Eq, Ordinalize)]
#[repr(usize)]
enum MyEnum {
    Zero,
    One,
    Two,
    Thousand = 1000,
}

assert_eq!(4, MyEnum::VARIANT_COUNT);
assert_eq!([MyEnum::Zero, MyEnum::One, MyEnum::Two, MyEnum::Thousand], MyEnum::VARIANTS);
assert_eq!([0usize, 1usize, 2usize, 1000usize], MyEnum::VALUES);

assert_eq!(0usize, MyEnum::Zero.ordinal());
assert_eq!(1usize, MyEnum::One.ordinal());
assert_eq!(2usize, MyEnum::Two.ordinal());

assert_eq!(Some(MyEnum::Zero), MyEnum::from_ordinal(0usize));
assert_eq!(Some(MyEnum::One), MyEnum::from_ordinal(1usize));
assert_eq!(Some(MyEnum::Two), MyEnum::from_ordinal(2usize));

assert_eq!(MyEnum::Zero, unsafe { MyEnum::from_ordinal_unsafe(0usize) });
assert_eq!(MyEnum::One, unsafe { MyEnum::from_ordinal_unsafe(1usize) });
assert_eq!(MyEnum::Two, unsafe { MyEnum::from_ordinal_unsafe(2usize) });

有用的增量

变体表示的整数可以按顺序增加,并从任何值显式设置。

use enum_ordinalize::Ordinalize;

#[derive(Debug, PartialEq, Eq, Ordinalize)]
enum MyEnum {
    Two   = 2,
    Three,
    Four,
    Eight = 8,
    Nine,
    NegativeTen = -10,
    NegativeNine,
}

assert_eq!(7, MyEnum::VARIANT_COUNT);
assert_eq!([MyEnum::Two, MyEnum::Three, MyEnum::Four, MyEnum::Eight, MyEnum::Nine, MyEnum::NegativeTen, MyEnum::NegativeNine], MyEnum::VARIANTS);
assert_eq!([2i8, 3i8, 4i8, 8i8, 9i8, -10i8, -9i8], MyEnum::VALUES);

assert_eq!(4i8, MyEnum::Four.ordinal());
assert_eq!(9i8, MyEnum::Nine.ordinal());
assert_eq!(-9i8, MyEnum::NegativeNine.ordinal());

assert_eq!(Some(MyEnum::Four), MyEnum::from_ordinal(4i8));
assert_eq!(Some(MyEnum::Nine), MyEnum::from_ordinal(9i8));
assert_eq!(Some(MyEnum::NegativeNine), MyEnum::from_ordinal(-9i8));

assert_eq!(MyEnum::Four, unsafe { MyEnum::from_ordinal_unsafe(4i8) });
assert_eq!(MyEnum::Nine, unsafe { MyEnum::from_ordinal_unsafe(9i8) });
assert_eq!(MyEnum::NegativeNine, unsafe { MyEnum::from_ordinal_unsafe(-9i8) });

为枚举实现自身上的功能

出于某种原因,如果您不想为您的枚举实现 Ordinalize 特性,您可以选择禁用特性实现并逐个启用常量/函数。函数是 const fn。名称和可见性也可以由您定义。

use enum_ordinalize::Ordinalize;

#[derive(Debug, PartialEq, Eq, Ordinalize)]
#[ordinalize(impl_trait = false)]
#[ordinalize(variant_count(pub const VARIANT_COUNT, doc = "The count of variants."))]
#[ordinalize(variants(pub const VARIANTS, doc = "List of this enum's variants."))]
#[ordinalize(values(pub const VALUES, doc = "List of values for all variants of this enum."))]
#[ordinalize(ordinal(pub const fn ordinal, doc = "Retrieve the integer number of this variant."))]
#[ordinalize(from_ordinal(pub const fn from_ordinal, doc = "Obtain a variant based on an integer number."))]
#[ordinalize(from_ordinal_unsafe(
    pub const fn from_ordinal_unsafe,
    doc = "Obtain a variant based on an integer number.",
    doc = "# Safety",
    doc = "You have to ensure that the input integer number can correspond to a variant on your own.",
))]
enum MyEnum {
    A,
    B,
}

assert_eq!(2, MyEnum::VARIANT_COUNT);
assert_eq!([MyEnum::A, MyEnum::B], MyEnum::VARIANTS);
assert_eq!([0i8, 1i8], MyEnum::VALUES);

assert_eq!(0i8, MyEnum::A.ordinal());
assert_eq!(1i8, MyEnum::B.ordinal());

assert_eq!(Some(MyEnum::A), MyEnum::from_ordinal(0i8));
assert_eq!(Some(MyEnum::B), MyEnum::from_ordinal(1i8));

assert_eq!(MyEnum::A, unsafe { MyEnum::from_ordinal_unsafe(0i8) });
assert_eq!(MyEnum::B, unsafe { MyEnum::from_ordinal_unsafe(1i8) });

Crates.io

https://crates.io/crates/enum-ordinalize

文档

https://docs.rs/enum-ordinalize

许可证

MIT

依赖项

~110KB