Skip to content

Commit 836b086

Browse files
committed
Implements DoubleEndedIterator for Leds
We can reverse now! Also removed the &Leds version of the iterator, because you can't do anything useful with it.
1 parent 8e88374 commit 836b086

File tree

3 files changed

+97
-104
lines changed

3 files changed

+97
-104
lines changed

examples/leds_array_indexing.rs renamed to examples/leds.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ fn main() -> ! {
2424

2525
// initialize user leds
2626
let mut gpioe = device_periphs.GPIOE.split(&mut reset_and_clock_control.ahb);
27-
let leds = Leds::new(
27+
let mut leds = Leds::new(
2828
gpioe.pe8,
2929
gpioe.pe9,
3030
gpioe.pe10,
@@ -37,17 +37,13 @@ fn main() -> ! {
3737
&mut gpioe.otyper,
3838
);
3939

40-
let mut compass = leds.into_array();
41-
4240
loop {
4341
let ms_delay = 50u16;
44-
let ubound = compass.len();
45-
for curr in 0..ubound {
46-
let next = (curr + 1) % ubound;
4742

48-
compass[next].on().ok();
43+
for led in &mut leds {
44+
led.on().ok();
4945
delay.delay_ms(ms_delay);
50-
compass[curr].off().ok();
46+
led.off().ok();
5147
delay.delay_ms(ms_delay);
5248
}
5349
}

examples/leds_array_iterator.rs renamed to examples/leds_iterator_test.rs

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,19 +41,43 @@ fn main() -> ! {
4141

4242
loop {
4343
let ms_delay = 50u16;
44-
// Alternative way to iterate through lights
45-
// do it backwards because it's fun and easy
46-
// for led in compass.iter_mut().rev() {
47-
// led.on().ok();
48-
// delay.delay_ms(ms_delay);
49-
// led.off().ok();
50-
// delay.delay_ms(ms_delay);
51-
// }
52-
for led in &mut leds {
44+
45+
// iterate through the leds in reverse
46+
for led in leds.iter_mut().rev() {
5347
led.on().ok();
5448
delay.delay_ms(ms_delay);
5549
led.off().ok();
5650
delay.delay_ms(ms_delay);
5751
}
52+
53+
delay.delay_ms(ms_delay);
54+
55+
// verify we stop when meeting in the middle
56+
let mut iter = leds.iter_mut();
57+
iter.next().map(|led| led.on().ok());
58+
delay.delay_ms(ms_delay);
59+
iter.next_back().map(|led| led.on().ok());
60+
delay.delay_ms(ms_delay);
61+
iter.next().map(|led| led.on().ok());
62+
delay.delay_ms(ms_delay);
63+
iter.next_back().map(|led| led.on().ok());
64+
delay.delay_ms(ms_delay);
65+
iter.next().map(|led| led.on().ok());
66+
delay.delay_ms(ms_delay);
67+
iter.next_back().map(|led| led.on().ok());
68+
delay.delay_ms(ms_delay);
69+
iter.next().map(|led| led.on().ok());
70+
delay.delay_ms(ms_delay);
71+
iter.next_back().map(|led| led.on().ok());
72+
delay.delay_ms(ms_delay);
73+
// we're in the middle, so panic if either of the next two calls returns a led
74+
iter.next().map(|_| panic!("Got a Some!"));
75+
iter.next_back().map(|_| panic!("Got a Some!"));
76+
77+
// turn everything back off
78+
for led in &mut leds {
79+
led.off().ok();
80+
delay.delay_ms(ms_delay);
81+
}
5882
}
5983
}

src/leds.rs

Lines changed: 60 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -128,10 +128,6 @@ impl Leds {
128128
}
129129
}
130130

131-
pub fn iter(&self) -> LedsIterator {
132-
LedsIterator::new(self)
133-
}
134-
135131
pub fn iter_mut(&mut self) -> LedsMutIterator {
136132
LedsMutIterator::new(self)
137133
}
@@ -154,15 +150,6 @@ impl Leds {
154150
}
155151
}
156152

157-
impl<'a> IntoIterator for &'a Leds {
158-
type Item = &'a Led;
159-
type IntoIter = LedsIterator<'a>;
160-
161-
fn into_iter(self) -> Self::IntoIter {
162-
self.iter()
163-
}
164-
}
165-
166153
impl<'a> IntoIterator for &'a mut Leds {
167154
type Item = &'a mut Led;
168155
type IntoIter = LedsMutIterator<'a>;
@@ -172,73 +159,21 @@ impl<'a> IntoIterator for &'a mut Leds {
172159
}
173160
}
174161

175-
pub struct LedsIterator<'a> {
176-
current_index: usize,
177-
leds: &'a Leds
178-
}
179-
180-
impl<'a> LedsIterator<'a> {
181-
fn new(leds: &'a Leds) -> Self {
182-
LedsIterator { current_index: 0, leds }
183-
}
184-
185-
fn len(&self) -> usize {
186-
ITERATOR_SIZE - self.current_index
187-
}
188-
189-
fn size_hint(&self) -> (usize, Option<usize>) {
190-
let length = self.len();
191-
(length, Some(length))
192-
}
193-
}
194-
195-
impl<'a> Iterator for LedsIterator<'a> {
196-
type Item = &'a Led;
197-
fn next(&mut self) -> Option<Self::Item> {
198-
let current = match self.current_index {
199-
0 => Some(&self.leds.ld3), //N
200-
1 => Some(&self.leds.ld5), //NE
201-
2 => Some(&self.leds.ld7), //E
202-
3 => Some(&self.leds.ld9), //SE
203-
4 => Some(&self.leds.ld10), //S
204-
5 => Some(&self.leds.ld8), //SW
205-
6 => Some(&self.leds.ld6), //W
206-
7 => Some(&self.leds.ld4), //NW
207-
_ => None
208-
};
209-
self.current_index += 1;
210-
current
211-
}
212-
213-
// Because we implement ExactSizedIterator, we need to ensure size_hint returns the right length
214-
fn size_hint(&self) -> (usize, Option<usize>) {
215-
self.size_hint()
216-
}
217-
}
218-
219162
const ITERATOR_SIZE: usize = 8;
220163

221-
impl<'a> ExactSizeIterator for LedsIterator<'a> {
222-
fn len(&self) -> usize {
223-
self.len()
224-
}
225-
}
226-
227-
///Marker trait that indicates LedsIterator never starts returning Some after returning None
228-
impl<'a> FusedIterator for LedsIterator<'a> {}
229-
230164
pub struct LedsMutIterator<'a> {
231-
current_index: usize,
165+
index: usize,
166+
index_back: usize,
232167
leds: &'a mut Leds
233168
}
234169

235170
impl<'a> LedsMutIterator<'a> {
236171
fn new(leds: &'a mut Leds) -> Self {
237-
LedsMutIterator { current_index: 0, leds }
172+
LedsMutIterator { index: 0, index_back: ITERATOR_SIZE, leds }
238173
}
239174

240175
fn len(&self) -> usize {
241-
ITERATOR_SIZE - self.current_index
176+
self.index_back - self.index
242177
}
243178

244179
fn size_hint(&self) -> (usize, Option<usize>) {
@@ -250,23 +185,28 @@ impl<'a> LedsMutIterator<'a> {
250185
impl<'a> Iterator for LedsMutIterator<'a> {
251186
type Item = &'a mut Led;
252187
fn next(&mut self) -> Option<Self::Item> {
253-
let current = unsafe {
254-
//Safety: Each branch is only executed once,
255-
// so we can not possibly alias a mutable reference.
256-
match self.current_index {
257-
0 => Some(&mut *(&mut self.leds.ld3 as *mut _)), //N
258-
1 => Some(&mut *(&mut self.leds.ld5 as *mut _)), //NE
259-
2 => Some(&mut *(&mut self.leds.ld7 as *mut _)), //E
260-
3 => Some(&mut *(&mut self.leds.ld9 as *mut _)), //SE
261-
4 => Some(&mut *(&mut self.leds.ld10 as *mut _)), //S
262-
5 => Some(&mut *(&mut self.leds.ld8 as *mut _)), //SW
263-
6 => Some(&mut *(&mut self.leds.ld6 as *mut _)), //W
264-
7 => Some(&mut *(&mut self.leds.ld4 as *mut _)), //NW
265-
_ => None
266-
}
267-
};
268-
self.current_index += 1;
269-
current
188+
if self.len() == 0 {
189+
None
190+
} else {
191+
let current = unsafe {
192+
//Safety: Each branch is only executed once,
193+
// so we can not possibly alias a mutable reference.
194+
// Oddly, this depends on DoubleSidedIterator also being implemented correctly.
195+
match self.index {
196+
0 => Some(&mut *(&mut self.leds.ld3 as *mut _)), //N
197+
1 => Some(&mut *(&mut self.leds.ld5 as *mut _)), //NE
198+
2 => Some(&mut *(&mut self.leds.ld7 as *mut _)), //E
199+
3 => Some(&mut *(&mut self.leds.ld9 as *mut _)), //SE
200+
4 => Some(&mut *(&mut self.leds.ld10 as *mut _)), //S
201+
5 => Some(&mut *(&mut self.leds.ld8 as *mut _)), //SW
202+
6 => Some(&mut *(&mut self.leds.ld6 as *mut _)), //W
203+
7 => Some(&mut *(&mut self.leds.ld4 as *mut _)), //NW
204+
_ => None
205+
}
206+
};
207+
self.index += 1;
208+
current
209+
}
270210
}
271211

272212
// Because we implement ExactSizedIterator, we need to ensure size_hint returns the right length
@@ -275,9 +215,42 @@ impl<'a> Iterator for LedsMutIterator<'a> {
275215
}
276216
}
277217

218+
impl<'a> DoubleEndedIterator for LedsMutIterator<'a> {
219+
fn next_back(&mut self) -> Option<Self::Item> {
220+
if self.len() == 0 {
221+
None
222+
} else {
223+
let current = unsafe {
224+
//Safety: Each branch is only executed once,
225+
// and only if there are elements left to be returned,
226+
// so we can not possibly alias a mutable reference.
227+
// This depends on Iterator and ExactSizedIterator being implemented correctly.
228+
// If len() does not return the correct number of remaining elements,
229+
// this becomes unsound.
230+
match self.index_back {
231+
// Because we're going backwards and index_back is a usize,
232+
// We use a one based index so we don't go negative
233+
0 => None, //done
234+
1 => Some(&mut *(&mut self.leds.ld3 as *mut _)), //N
235+
2 => Some(&mut *(&mut self.leds.ld5 as *mut _)), //NE
236+
3 => Some(&mut *(&mut self.leds.ld7 as *mut _)), //E
237+
4 => Some(&mut *(&mut self.leds.ld9 as *mut _)), //SE
238+
5 => Some(&mut *(&mut self.leds.ld10 as *mut _)), //S
239+
6 => Some(&mut *(&mut self.leds.ld8 as *mut _)), //SW
240+
7 => Some(&mut *(&mut self.leds.ld6 as *mut _)), //W
241+
8 => Some(&mut *(&mut self.leds.ld4 as *mut _)), //NW
242+
_ => None //can't happen
243+
}
244+
};
245+
self.index_back -= 1;
246+
current
247+
}
248+
}
249+
}
250+
278251
impl<'a> ExactSizeIterator for LedsMutIterator<'a> {
279252
fn len(&self) -> usize {
280-
ITERATOR_SIZE - self.current_index
253+
self.len()
281254
}
282255
}
283256

0 commit comments

Comments
 (0)