3个版本
0.1.2 | 2021年1月26日 |
---|---|
0.1.1 | 2021年1月25日 |
0.1.0 | 2021年1月24日 |
#1015 in 过程宏
16KB
118 行
rotate-enum 包
简单的派生宏,为Rust中的枚举实现prev()和next()方法
动机
有时你定义一个枚举,如下所示
enum Direction {
Up,
Left,
Down,
Right,
}
并希望在某种逻辑中旋转它们
let up = Direction::Up;
let left = Direction::Left;
let down = Direction::Down;
let right = Direction::Right;
assert!(up.next() == left);
assert!(left.next() == down);
assert!(down.next() == right);
assert!(right.next() == up);
assert!(up.prev() == right);
assert!(left.prev() == up);
assert!(down.prev() == left);
assert!(right.prev() == down);
当然,你可以手动实现这些方法,但这很重复且容易出错。你不认为应该自动化吗?这个crate提供了一个RotateEnum
派生宏来完成这项工作。
移位
这个crate还提供了ShiftEnum
,它会在枚举列表的末尾耗尽,而不是旋转。
let up = Direction::Up;
let left = Direction::Left;
let down = Direction::Down;
let right = Direction::Right;
assert!(up.next() == Some(left));
assert!(left.next() == Some(down));
assert!(down.next() == Some(right));
assert!(right.next() == None);
assert!(up.prev() == None);
assert!(left.prev() == Some(up));
assert!(down.prev() == Some(left));
assert!(right.prev() == Some(down));
请注意,你只能派生RotateEnum
或ShiftEnum
中的一个,而不能同时派生两个,因为它们的语义冲突。
迭代
这个crate还提供了IterEnum
,它将实现一个Iterator
对象,按顺序生成枚举变体。第一个生成结果是开始迭代时的同一变体,即Direction::Up.iter().next() == Some(Direction::Up)
。
let up = Direction::Up;
let left = Direction::Left;
let down = Direction::Down;
let right = Direction::Right;
let mut iter = up.iter();
assert!(iter.next() == Some(up));
assert!(iter.next() == Some(left));
assert!(iter.next() == Some(down));
assert!(iter.next() == Some(right));
assert!(iter.next() == None);
assert_eq!(up.iter().collect::<Vec<_>>(), vec![up, left, down, right]);
请注意,这与ShiftEnum
不同,因为迭代器是单向的,这意味着你可以向前移动,但不能prev()
。它也可以与迭代器方法(如collect()
)一起使用。
IterEnum
还需要派生Clone
。
用法
使用 #[derive(...)]
宏来注解您的枚举。
use rotate_enum::RotateEnum;
#[derive(RotateEnum)]
enum Direction {
Up,
Left,
Down,
Right,
}
依赖关系
~1.5MB
~35K SLoC