18个版本
0.1.17 | 2023年12月21日 |
---|---|
0.1.16 | 2023年8月6日 |
0.1.15 | 2023年7月29日 |
0.1.13 | 2023年6月20日 |
0.1.10 | 2022年9月24日 |
#663 在 过程宏 中
在 2 个crate中使用(通过 bones3_worldgen)
65KB
1K SLoC
sort_by_derive
此crate提供3个派生宏 SortBy
、EnumAccessor
和 EnumSequence
。
SortBy
为无法自动派生这些特质的结构派生特质Ord
、PartialOrd
、Eq
、PartialEq
和Hash
。- 在枚举和结构体上,
SortBy
还可以实现一个调用任意方法的Ord
特质,这特别适用于与由EnumAccessor
和EnumSequence
派生的枚举变体访问方法结合使用。 EnumAccessor
为变体中的常用字段派生访问器方法,因此您无需编写自己的match
语句来访问具有相同名称和类型的字段。此功能类似于 enum_dispatch,但采用不同的方法,其中结构体不需要实现特质。EnumSequence
提供了一个enum_sequence
方法,其中第一个变体返回0
,第二个返回1
,依此类推。这在需要实现自定义排序时很有用,同时变体声明的顺序仍然是作为次要排序依据。
用法
SortBy
应用于排序的字段使用属性 #[sort_by]
标记。其他字段将被忽略。
use std::cmp::Ordering;
use sort_by_derive::SortBy;
#[derive(SortBy)]
struct Something {
#[sort_by]
a: u16,
b: u16
}
assert_eq!(Something{a: 2, b: 0}.cmp(&Something{a: 1, b: 1}), Ordering::Greater); // a is compared
assert_eq!(Something{a: 1, b: 0}.cmp(&Something{a: 1, b: 1}), Ordering::Equal); // b is ignored
枚举访问器
此 derive 宏与 enum_dispatch 类似。 enum_dispatch
要求结构体实现一个公共特质,如果一组公共函数适用于所有变体,这可能会很有用。 EnumAccessor
采取了相反的方法:公共字段和方法在枚举级别声明,并且可以存在没有给定字段或方法的变体。如果变体数量很多,而你只关心访问字段,这可能更实用,因为单个结构体仅包含数据。这通常适用于事件——它们代表状态变化,通常作为一个整体被消费,单个结构体没有自己的代码。
字段访问器
在枚举上添加 derive(EnumAccessor)
之后,字段将声明为 accessor(field: type)
属性。
这将推导出访问器方法 fn name(&self) -> &type;
和 fn name_mut(&mut self) -> &mut type;
,并返回任何变体上同名字段的引用。
use sort_by_derive::EnumAccessor;
#[derive(EnumAccessor)]
#[accessor(a: u16)]
#[accessor(b: u16)]
enum E {
Variant1{a: u16, b: u16},
Variant2{a: u16, b: u16, c: u32},
}
let v1 = E::Variant1{a: 1, b: 1};
let mut v2 = E::Variant2{a: 1, b: 1, c: 2};
// Accessor methods are generated for the specified members
assert_eq!(*v1.a(), 1);
assert_eq!(*v2.b(), 1);
// Mutable accessors are also generated
*v2.a_mut() = 2;
assert_eq!(*v2.a(), 2);
因此,您可以取任何 E
,所有变体都将有 a
、a_mut
、b
、b_mut
。
枚举序列
只需简单地 derive EnumSequence
,您就可以得到 enum_sequence(&self)
,它返回一个从 0
开始并针对每个变体递增的 usize
。
当使用枚举的枚举时,创建对内部枚举序列的访问器可能会创建方法名歧义。为了减轻这种情况,可以使用 as
选择自定义访问器名称,例如 #[accessor(enum_sequence() as inner_sequence: usize)]
注意:这将创建一个扩展特质 {TypeName}EnumSequence
(即类型 T
将获得一个新的特质 TEnumSequence
)。此特质将具有与类型相同的可见性。当从另一个模块使用此类型时,请确保使用 use {TypeName}EnumSequence
带入特质的作用域。
示例
use sort_by_derive::EnumSequence;
#[derive(EnumSequence)]
enum ABC {
A(u8),
B(String),
C { f: String, g: usize }
}
assert_eq!(ABC::B("hi!".into()).enum_sequence(), 1);
依赖项
~0.5–1MB
~21K SLoC