1use crate::{Position, Step};
3
4pub trait Pattern {
15 fn next_action(&mut self) -> Option<Action>;
17
18 fn next_action_peek(&self) -> Option<Action>;
21
22 fn repeat(&self) -> &Repeat;
24
25 fn rest_steps(&self) -> Option<Vec<Step>> {
32 if matches!(self.next_action_peek(), Some(Action::StepFromOrigin(_))) {
33 panic!("Action::StepFromOrigin must implement rest_step");
34 }
35 None
36 }
37
38 fn rest_positions(&self) -> Option<Vec<Position>> {
42 if matches!(self.next_action_peek(), Some(Action::Jump(_))) {
43 panic!("Action::Jump must implement rest_positions");
44 }
45 None
46 }
47}
48
49#[derive(Copy, Clone, Debug, PartialEq, Eq)]
52pub enum Action {
53 Step(Step),
56
57 StepFromOrigin(Step),
61
62 Jump(Position),
65}
66
67#[derive(Copy, Clone, Debug, PartialEq, Eq)]
69pub enum Repeat {
70 Once,
71 TillEnd,
72 Times(usize),
73}
74
75#[derive(Copy, Clone, Debug, PartialEq, Eq)]
77pub struct DirectionPattern {
78 pub(crate) step: Step,
79 pub(crate) repeat: Repeat,
80}
81
82impl DirectionPattern {
83 pub fn new<S: Into<Step>>(step: S, repeat: Repeat) -> Self {
84 Self {
85 step: step.into(),
86 repeat,
87 }
88 }
89}
90
91impl Pattern for DirectionPattern {
92 fn next_action(&mut self) -> Option<Action> {
93 Some(Action::Step(self.step))
94 }
95
96 fn next_action_peek(&self) -> Option<Action> {
97 Some(Action::Step(self.step))
98 }
99
100 fn repeat(&self) -> &Repeat {
101 &self.repeat
102 }
103}
104
105pub struct StepsPattern {
107 pub(crate) steps: Vec<Step>,
108 pub(crate) idx: usize,
109}
110
111impl StepsPattern {
112 pub fn new<T: Copy + Into<Step>>(steps: Vec<T>) -> Self {
113 Self {
114 steps: steps.iter().map(|t| (*t).into()).collect(),
115 idx: 0,
116 }
117 }
118}
119
120impl Pattern for StepsPattern {
121 fn next_action(&mut self) -> Option<Action> {
122 self.idx += 1;
123 Some(Action::Step(*self.steps.get(self.idx - 1)?))
124 }
125
126 fn next_action_peek(&self) -> Option<Action> {
127 Some(Action::Step(*self.steps.get(self.idx)?))
128 }
129
130 fn repeat(&self) -> &Repeat {
131 &Repeat::TillEnd
132 }
133}
134
135pub struct SideStepsPattern {
138 pub(crate) steps: Vec<Step>,
139 pub(crate) idx: usize,
140}
141
142impl SideStepsPattern {
143 pub fn new<I>(steps: I) -> Self
144 where
145 I: IntoIterator,
146 I::Item: Copy + Into<Step>,
147 {
148 Self {
149 steps: steps.into_iter().map(|t| t.into()).collect(),
150 idx: 0,
151 }
152 }
153}
154
155impl Pattern for SideStepsPattern {
156 fn next_action(&mut self) -> Option<Action> {
157 self.idx += 1;
158 Some(Action::StepFromOrigin(*self.steps.get(self.idx - 1)?))
159 }
160
161 fn next_action_peek(&self) -> Option<Action> {
162 Some(Action::StepFromOrigin(*self.steps.get(self.idx)?))
163 }
164
165 fn repeat(&self) -> &Repeat {
166 &Repeat::TillEnd
167 }
168
169 fn rest_steps(&self) -> Option<Vec<Step>> {
170 Some(self.steps[self.idx..].iter().copied().collect())
171 }
172}
173
174pub struct JumpsPattern {
177 jumps: Vec<Position>,
178 idx: usize,
179}
180
181impl JumpsPattern {
182 pub fn new<I>(positions: I) -> Self
183 where
184 I: IntoIterator,
185 I::Item: Copy + Into<Position>,
186 {
187 Self {
188 jumps: positions.into_iter().map(|t| t.into()).collect(),
189 idx: 0,
190 }
191 }
192}
193
194impl Pattern for JumpsPattern {
195 fn next_action(&mut self) -> Option<Action> {
196 self.idx += 1;
197 Some(Action::Jump(*self.jumps.get(self.idx - 1)?))
198 }
199
200 fn next_action_peek(&self) -> Option<Action> {
201 Some(Action::Jump(*self.jumps.get(self.idx)?))
202 }
203
204 fn repeat(&self) -> &Repeat {
205 &Repeat::TillEnd
206 }
207
208 fn rest_positions(&self) -> Option<Vec<Position>> {
209 Some(self.jumps[self.idx..].iter().copied().collect())
210 }
211}