@@ -5,6 +5,7 @@ use stm32f3xx_hal::gpio::{Output, PushPull};
5
5
use switch_hal:: { ActiveHigh , IntoSwitch , OutputSwitch , Switch } ;
6
6
7
7
use core:: slice:: Iter ;
8
+ use core:: iter:: FusedIterator ;
8
9
9
10
/// LED compass direction as noted on the board
10
11
#[ derive( Clone , Copy , Eq , PartialEq ) ]
@@ -21,6 +22,9 @@ pub enum Direction
21
22
}
22
23
23
24
impl Direction {
25
+ /// Provides an iterator starting with North
26
+ /// and moving clockwise around the compass
27
+ /// e.g. N -> NE -> E, etc.
24
28
pub fn iter ( ) -> Iter < ' static , Direction > {
25
29
static DIRECTIONS : [ Direction ; 8 ] = [
26
30
Direction :: North ,
@@ -106,15 +110,9 @@ impl Leds {
106
110
. into_active_high_switch ( ) ,
107
111
} ;
108
112
109
- //TODO: expose an iterator
110
- leds. ld3 . off ( ) . ok ( ) ;
111
- leds. ld4 . off ( ) . ok ( ) ;
112
- leds. ld5 . off ( ) . ok ( ) ;
113
- leds. ld6 . off ( ) . ok ( ) ;
114
- leds. ld7 . off ( ) . ok ( ) ;
115
- leds. ld8 . off ( ) . ok ( ) ;
116
- leds. ld9 . off ( ) . ok ( ) ;
117
- leds. ld10 . off ( ) . ok ( ) ;
113
+ for led in & mut leds {
114
+ led. off ( ) . ok ( ) ;
115
+ }
118
116
119
117
leds
120
118
}
@@ -133,9 +131,17 @@ impl Leds {
133
131
}
134
132
}
135
133
134
+ /// Provides a mutable iterator for iterating over the on board leds.
135
+ /// Starts at ld3 (N) and moves clockwise.
136
+ /// Stops once it has iterated through all 8 leds.
137
+ pub fn iter_mut ( & mut self ) -> LedsMutIterator {
138
+ LedsMutIterator :: new ( self )
139
+ }
140
+
136
141
/// Consumes the `Leds` struct and returns an array
137
142
/// where index 0 is N and each incrementing index
138
143
/// rotates clockwise around the compass
144
+ #[ deprecated( since = "0.7.1" , note = "Use `iter_mut()` intsead. This will be removed in 0.8.0" ) ]
139
145
pub fn into_array ( self ) -> [ Led ; 8 ] {
140
146
[
141
147
self . ld3 , //N
@@ -149,3 +155,113 @@ impl Leds {
149
155
]
150
156
}
151
157
}
158
+
159
+ impl < ' a > IntoIterator for & ' a mut Leds {
160
+ type Item = & ' a mut Led ;
161
+ type IntoIter = LedsMutIterator < ' a > ;
162
+
163
+ fn into_iter ( self ) -> Self :: IntoIter {
164
+ self . iter_mut ( )
165
+ }
166
+ }
167
+
168
+ const ITERATOR_SIZE : usize = 8 ;
169
+
170
+ pub struct LedsMutIterator < ' a > {
171
+ index : usize ,
172
+ index_back : usize ,
173
+ leds : & ' a mut Leds
174
+ }
175
+
176
+ impl < ' a > LedsMutIterator < ' a > {
177
+ fn new ( leds : & ' a mut Leds ) -> Self {
178
+ LedsMutIterator { index : 0 , index_back : ITERATOR_SIZE , leds }
179
+ }
180
+
181
+ fn len ( & self ) -> usize {
182
+ self . index_back - self . index
183
+ }
184
+
185
+ fn size_hint ( & self ) -> ( usize , Option < usize > ) {
186
+ let length = self . len ( ) ;
187
+ ( length, Some ( length) )
188
+ }
189
+ }
190
+
191
+ impl < ' a > Iterator for LedsMutIterator < ' a > {
192
+ type Item = & ' a mut Led ;
193
+ fn next ( & mut self ) -> Option < Self :: Item > {
194
+ if self . len ( ) == 0 {
195
+ None
196
+ } else {
197
+ let current = unsafe {
198
+ //Safety: Each branch is only executed once,
199
+ // and only if there are elements left to be returned,
200
+ // so we can not possibly alias a mutable reference.
201
+ // This depends on DoubleEndedIterator and ExactSizedIterator being implemented correctly.
202
+ // If len() does not return the correct number of remaining elements,
203
+ // this becomes unsound.
204
+ match self . index {
205
+ 0 => Some ( & mut * ( & mut self . leds . ld3 as * mut _ ) ) , //N
206
+ 1 => Some ( & mut * ( & mut self . leds . ld5 as * mut _ ) ) , //NE
207
+ 2 => Some ( & mut * ( & mut self . leds . ld7 as * mut _ ) ) , //E
208
+ 3 => Some ( & mut * ( & mut self . leds . ld9 as * mut _ ) ) , //SE
209
+ 4 => Some ( & mut * ( & mut self . leds . ld10 as * mut _ ) ) , //S
210
+ 5 => Some ( & mut * ( & mut self . leds . ld8 as * mut _ ) ) , //SW
211
+ 6 => Some ( & mut * ( & mut self . leds . ld6 as * mut _ ) ) , //W
212
+ 7 => Some ( & mut * ( & mut self . leds . ld4 as * mut _ ) ) , //NW
213
+ _ => None
214
+ }
215
+ } ;
216
+ self . index += 1 ;
217
+ current
218
+ }
219
+ }
220
+
221
+ // Because we implement ExactSizedIterator, we need to ensure size_hint returns the right length
222
+ fn size_hint ( & self ) -> ( usize , Option < usize > ) {
223
+ self . size_hint ( )
224
+ }
225
+ }
226
+
227
+ impl < ' a > DoubleEndedIterator for LedsMutIterator < ' a > {
228
+ fn next_back ( & mut self ) -> Option < Self :: Item > {
229
+ if self . len ( ) == 0 {
230
+ None
231
+ } else {
232
+ let current = unsafe {
233
+ //Safety: Each branch is only executed once,
234
+ // and only if there are elements left to be returned,
235
+ // so we can not possibly alias a mutable reference.
236
+ // This depends on Iterator and ExactSizedIterator being implemented correctly.
237
+ // If len() does not return the correct number of remaining elements,
238
+ // this becomes unsound.
239
+ match self . index_back {
240
+ // Because we're going backwards and index_back is a usize,
241
+ // We use a one based index so we don't go negative
242
+ 0 => None , //done
243
+ 1 => Some ( & mut * ( & mut self . leds . ld3 as * mut _ ) ) , //N
244
+ 2 => Some ( & mut * ( & mut self . leds . ld5 as * mut _ ) ) , //NE
245
+ 3 => Some ( & mut * ( & mut self . leds . ld7 as * mut _ ) ) , //E
246
+ 4 => Some ( & mut * ( & mut self . leds . ld9 as * mut _ ) ) , //SE
247
+ 5 => Some ( & mut * ( & mut self . leds . ld10 as * mut _ ) ) , //S
248
+ 6 => Some ( & mut * ( & mut self . leds . ld8 as * mut _ ) ) , //SW
249
+ 7 => Some ( & mut * ( & mut self . leds . ld6 as * mut _ ) ) , //W
250
+ 8 => Some ( & mut * ( & mut self . leds . ld4 as * mut _ ) ) , //NW
251
+ _ => None //can't happen
252
+ }
253
+ } ;
254
+ self . index_back -= 1 ;
255
+ current
256
+ }
257
+ }
258
+ }
259
+
260
+ impl < ' a > ExactSizeIterator for LedsMutIterator < ' a > {
261
+ fn len ( & self ) -> usize {
262
+ self . len ( )
263
+ }
264
+ }
265
+
266
+ ///Marker trait that indicates LedsMutIterator never starts returning Some after returning None
267
+ impl < ' a > FusedIterator for LedsMutIterator < ' a > { }
0 commit comments