Skip to content

Commit a251cbf

Browse files
witek103Dirbaio
authored andcommitted
histbuf: Implement DoubleEndedIterator for OldestOrdered
Rewrite Iterator for OldestOrdered and add DoubleEndedIterator implementation. Update HistoryBuffer oldest_ordered() to reflect changes. Signed-off-by: Witold Lipieta <witek103@gmail.com>
1 parent 39c379c commit a251cbf

File tree

2 files changed

+58
-22
lines changed

2 files changed

+58
-22
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
2323
- Added `serde::Serialize` and `serde::Deserialize` implementations to `HistoryBuffer`.
2424
- Added `Vec::drain`.
2525
- Added `String::drain`.
26+
- Implemented `DoubleEndedIterator` for `OldestOrdered`.
2627

2728
### Changed
2829

src/histbuf.rs

Lines changed: 57 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,8 @@ impl<T, const N: usize> HistoryBuffer<T, N> {
283283
}
284284
}
285285

286-
/// Returns an iterator for iterating over the buffer from oldest to newest.
286+
/// Returns double ended iterator for iterating over the buffer from
287+
/// the oldest to the newest and back.
287288
///
288289
/// # Examples
289290
///
@@ -298,19 +299,19 @@ impl<T, const N: usize> HistoryBuffer<T, N> {
298299
/// }
299300
/// ```
300301
pub fn oldest_ordered(&self) -> OldestOrdered<'_, T, N> {
301-
if self.filled {
302-
OldestOrdered {
302+
match (self.oldest_index(), self.recent_index()) {
303+
(Some(oldest_index), Some(recent_index)) => OldestOrdered {
303304
buf: self,
304-
cur: self.write_at,
305-
wrapped: false,
306-
}
307-
} else {
308-
// special case: act like we wrapped already to handle empty buffer.
309-
OldestOrdered {
305+
next: oldest_index,
306+
back: recent_index,
307+
done: false,
308+
},
309+
_ => OldestOrdered {
310310
buf: self,
311-
cur: 0,
312-
wrapped: true,
313-
}
311+
next: 0,
312+
back: 0,
313+
done: true,
314+
},
314315
}
315316
}
316317
}
@@ -403,30 +404,50 @@ where
403404
}
404405
}
405406

406-
/// An iterator on the underlying buffer ordered from oldest data to newest
407+
/// Double ended iterator on the underlying buffer ordered from the oldest data
408+
/// to the newest
407409
#[derive(Clone)]
408410
pub struct OldestOrdered<'a, T, const N: usize> {
409411
buf: &'a HistoryBuffer<T, N>,
410-
cur: usize,
411-
wrapped: bool,
412+
next: usize,
413+
back: usize,
414+
done: bool,
412415
}
413416

414417
impl<'a, T, const N: usize> Iterator for OldestOrdered<'a, T, N> {
415418
type Item = &'a T;
416419

417420
fn next(&mut self) -> Option<&'a T> {
418-
if self.cur == self.buf.len() && self.buf.filled {
419-
// roll-over
420-
self.cur = 0;
421-
self.wrapped = true;
421+
if self.done {
422+
return None;
422423
}
423424

424-
if self.cur == self.buf.write_at && self.wrapped {
425+
if self.next == self.back {
426+
self.done = true;
427+
}
428+
429+
let item = &self.buf[self.next];
430+
431+
self.next = if self.next == N - 1 { 0 } else { self.next + 1 };
432+
433+
Some(item)
434+
}
435+
}
436+
437+
impl<'a, T, const N: usize> DoubleEndedIterator for OldestOrdered<'a, T, N> {
438+
fn next_back(&mut self) -> Option<Self::Item> {
439+
if self.done {
425440
return None;
426441
}
427442

428-
let item = &self.buf[self.cur];
429-
self.cur += 1;
443+
if self.next == self.back {
444+
self.done = true;
445+
}
446+
447+
let item = &self.buf[self.back];
448+
449+
self.back = if self.back == 0 { N - 1 } else { self.back - 1 };
450+
430451
Some(item)
431452
}
432453
}
@@ -609,18 +630,28 @@ mod tests {
609630
let mut iter = buffer.oldest_ordered();
610631
assert_eq!(iter.next(), None);
611632
assert_eq!(iter.next(), None);
633+
assert_eq!(iter.next_back(), None);
634+
assert_eq!(iter.next_back(), None);
612635

613636
// test on a un-filled buffer
614637
let mut buffer: HistoryBuffer<u8, 6> = HistoryBuffer::new();
615638
buffer.extend([1, 2, 3]);
616639
assert_eq!(buffer.len(), 3);
617640
assert_eq_iter(buffer.oldest_ordered(), &[1, 2, 3]);
641+
assert_eq_iter(buffer.oldest_ordered().rev(), &[3, 2, 1]);
642+
let mut iter = buffer.oldest_ordered();
643+
assert_eq!(iter.next(), Some(&1));
644+
assert_eq!(iter.next_back(), Some(&3));
645+
assert_eq!(iter.next_back(), Some(&2));
646+
assert_eq!(iter.next_back(), None);
647+
assert_eq!(iter.next(), None);
618648

619649
// test on a filled buffer
620650
let mut buffer: HistoryBuffer<u8, 6> = HistoryBuffer::new();
621651
buffer.extend([0, 0, 0, 1, 2, 3, 4, 5, 6]);
622652
assert_eq!(buffer.len(), 6);
623653
assert_eq_iter(buffer.oldest_ordered(), &[1, 2, 3, 4, 5, 6]);
654+
assert_eq_iter(buffer.oldest_ordered().rev(), &[6, 5, 4, 3, 2, 1]);
624655

625656
// comprehensive test all cases
626657
for n in 0..50 {
@@ -631,6 +662,10 @@ mod tests {
631662
buffer.oldest_ordered().copied(),
632663
n.saturating_sub(N as u8)..n,
633664
);
665+
assert_eq_iter(
666+
buffer.oldest_ordered().rev().copied(),
667+
(n.saturating_sub(N as u8)..n).rev(),
668+
);
634669
}
635670
}
636671

0 commit comments

Comments
 (0)