1use std::ops::Not;
2
3use self::Stroke::{Back, Hand};
4
5#[cfg(feature = "serde")]
6use serde_crate::{Deserialize, Serialize};
7
8#[repr(u8)]
10#[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash)]
11#[cfg_attr(
12 feature = "serde",
13 derive(Deserialize, Serialize),
14 serde(crate = "serde_crate", rename_all = "snake_case")
15)]
16pub enum Stroke {
17 Hand = 0,
18 Back = 1,
19}
20
21impl Stroke {
22 pub fn offset(self, offset: usize) -> Stroke {
36 if offset % 2 == 0 {
37 self
38 } else {
39 !self
40 }
41 }
42
43 pub fn offset_i(self, offset: isize) -> Stroke {
58 if offset % 2 == 0 {
59 self
60 } else {
61 !self
62 }
63 }
64}
65
66impl Not for Stroke {
67 type Output = Self;
68
69 fn not(self) -> Self::Output {
80 match self {
81 Hand => Back,
82 Back => Hand,
83 }
84 }
85}
86
87#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
89pub enum StrokeSet {
90 Hand,
91 Back,
92 Both,
93}
94
95impl StrokeSet {
96 pub fn contains(self, stroke: Stroke) -> bool {
97 match self {
98 Self::Both => true,
99 Self::Hand => stroke == Stroke::Hand,
100 Self::Back => stroke == Stroke::Back,
101 }
102 }
103}
104
105#[cfg(test)]
106mod tests {
107 use super::*;
108
109 #[test]
110 fn offset() {
111 #[track_caller]
112 fn check(start: Stroke, offset: usize, expected: Stroke) {
113 assert_eq!(start.offset(offset), expected);
114 }
115 check(Hand, 0, Hand);
116 check(Back, 0, Back);
117 check(Hand, 1, Back);
118 check(Back, 1, Hand);
119 check(Hand, 123547, Back);
120 check(Back, 123547, Hand);
121 check(Hand, usize::MAX, Back); check(Back, usize::MAX, Hand);
123 }
124
125 #[test]
126 fn offset_i() {
127 #[track_caller]
128 fn check(start: Stroke, offset: isize, expected: Stroke) {
129 assert_eq!(start.offset_i(offset), expected);
130 }
131 check(Hand, 0, Hand);
132 check(Back, 0, Back);
133 check(Hand, 1, Back);
134 check(Back, 1, Hand);
135 check(Hand, 123547, Back);
136 check(Back, 123547, Hand);
137 check(Hand, isize::MAX, Back); check(Back, isize::MAX, Hand);
139 check(Hand, isize::MIN, Hand); check(Back, isize::MIN, Back);
141 }
142
143 #[test]
144 fn not() {
145 assert_eq!(!Hand, Back);
146 assert_eq!(!Back, Hand);
147 }
148}