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