Skip to content

Commit 344eba1

Browse files
authored
Merge pull request #142 from cdellacqua/nth
Implement nth and nth_back to provide a O(1) way of skipping through elements
2 parents b6e1ec7 + 3a26f4d commit 344eba1

File tree

4 files changed

+116
-2
lines changed

4 files changed

+116
-2
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ categories = ["data-structures"]
1414
license = "MIT"
1515

1616
[dev-dependencies]
17-
criterion = "0.4.0"
17+
criterion = { version = "0.4.0", features = ["html_reports"] }
1818
compiletest_rs = "0.10.0"
1919

2020
[features]

benches/bench.rs

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
#![no_coverage]
1+
#![feature(coverage_attribute)]
2+
#![coverage(off)]
23
use criterion::{black_box, criterion_group, criterion_main, Bencher, Criterion};
34
use ringbuffer::{AllocRingBuffer, ConstGenericRingBuffer, RingBuffer};
45

@@ -63,6 +64,16 @@ fn benchmark_various<T: RingBuffer<i32>, F: Fn() -> T>(b: &mut Bencher, new: F)
6364
})
6465
}
6566

67+
fn benchmark_skip<T: RingBuffer<i32>, F: Fn() -> T>(b: &mut Bencher, new: F) {
68+
let mut rb = new();
69+
rb.fill(9);
70+
b.iter(|| {
71+
for i in 0..rb.len() {
72+
assert_eq!(rb.iter().skip(i).next(), Some(&9));
73+
}
74+
})
75+
}
76+
6677
macro_rules! generate_benches {
6778
(called, $c: tt, $rb: tt, $ty: tt, $fn: tt, $bmfunc: tt, $($i:tt),*) => {
6879
$(
@@ -180,6 +191,32 @@ fn criterion_benchmark(c: &mut Criterion) {
180191
8192,
181192
8195
182193
];
194+
generate_benches![
195+
typed,
196+
c,
197+
ConstGenericRingBuffer,
198+
i32,
199+
new,
200+
benchmark_skip,
201+
16,
202+
1024,
203+
4096,
204+
8192
205+
];
206+
generate_benches![
207+
called,
208+
c,
209+
AllocRingBuffer,
210+
i32,
211+
new,
212+
benchmark_skip,
213+
16,
214+
17,
215+
1024,
216+
4096,
217+
8192,
218+
8195
219+
];
183220
}
184221

185222
criterion_group!(benches, criterion_benchmark);

src/lib.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1449,4 +1449,61 @@ mod tests {
14491449
test_clone!(GrowableAllocRingBuffer::<_>::new());
14501450
test_clone!(AllocRingBuffer::<_>::new(4));
14511451
}
1452+
1453+
#[test]
1454+
fn iter_nth_override() {
1455+
macro_rules! test_concrete {
1456+
($rb_init: expr) => {
1457+
let rb = $rb_init([1, 2, 3, 4]);
1458+
assert_eq!(rb.iter().nth(0), Some(&1));
1459+
assert_eq!(rb.iter().nth(1), Some(&2));
1460+
assert_eq!(rb.iter().nth(2), Some(&3));
1461+
assert_eq!(rb.iter().nth(3), Some(&4));
1462+
assert_eq!(rb.iter().nth(4), None);
1463+
1464+
let mut rb = $rb_init([1, 2, 3, 4]);
1465+
assert_eq!(rb.iter_mut().nth(0), Some(&mut 1));
1466+
assert_eq!(rb.iter_mut().nth(1), Some(&mut 2));
1467+
assert_eq!(rb.iter_mut().nth(2), Some(&mut 3));
1468+
assert_eq!(rb.iter_mut().nth(3), Some(&mut 4));
1469+
assert_eq!(rb.iter_mut().nth(4), None);
1470+
1471+
let rb = $rb_init([1, 2, 3, 4]);
1472+
assert_eq!(rb.clone().into_iter().nth(0), Some(1));
1473+
assert_eq!(rb.clone().into_iter().nth(1), Some(2));
1474+
assert_eq!(rb.clone().into_iter().nth(2), Some(3));
1475+
assert_eq!(rb.clone().into_iter().nth(3), Some(4));
1476+
assert_eq!(rb.clone().into_iter().nth(4), None);
1477+
};
1478+
}
1479+
1480+
test_concrete!(|values: [i32; 4]| ConstGenericRingBuffer::<_, 4>::from(values));
1481+
test_concrete!(|values: [i32; 4]| GrowableAllocRingBuffer::<_>::from(values));
1482+
test_concrete!(|values: [i32; 4]| AllocRingBuffer::<_>::from(values));
1483+
}
1484+
1485+
#[test]
1486+
fn iter_nth_back_override() {
1487+
macro_rules! test_concrete {
1488+
($rb_init: expr) => {
1489+
let rb = $rb_init([1, 2, 3, 4]);
1490+
assert_eq!(rb.iter().nth_back(0), Some(&4));
1491+
assert_eq!(rb.iter().nth_back(1), Some(&3));
1492+
assert_eq!(rb.iter().nth_back(2), Some(&2));
1493+
assert_eq!(rb.iter().nth_back(3), Some(&1));
1494+
assert_eq!(rb.iter().nth_back(4), None);
1495+
1496+
let mut rb = $rb_init([1, 2, 3, 4]);
1497+
assert_eq!(rb.iter_mut().nth_back(0), Some(&mut 4));
1498+
assert_eq!(rb.iter_mut().nth_back(1), Some(&mut 3));
1499+
assert_eq!(rb.iter_mut().nth_back(2), Some(&mut 2));
1500+
assert_eq!(rb.iter_mut().nth_back(3), Some(&mut 1));
1501+
assert_eq!(rb.iter_mut().nth_back(4), None);
1502+
};
1503+
}
1504+
1505+
test_concrete!(|values: [i32; 4]| ConstGenericRingBuffer::<_, 4>::from(values));
1506+
test_concrete!(|values: [i32; 4]| GrowableAllocRingBuffer::<_>::from(values));
1507+
test_concrete!(|values: [i32; 4]| AllocRingBuffer::<_>::from(values));
1508+
}
14521509
}

src/ringbuffer_trait.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,11 @@ mod iter {
299299
fn size_hint(&self) -> (usize, Option<usize>) {
300300
(self.len, Some(self.len))
301301
}
302+
303+
fn nth(&mut self, n: usize) -> Option<Self::Item> {
304+
self.index = (self.index + n).min(self.len);
305+
self.next()
306+
}
302307
}
303308

304309
impl<'rb, T: 'rb, RB: RingBuffer<T>> FusedIterator for RingBufferIterator<'rb, T, RB> {}
@@ -316,6 +321,11 @@ mod iter {
316321
None
317322
}
318323
}
324+
325+
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
326+
self.len = self.len - n.min(self.len);
327+
self.next_back()
328+
}
319329
}
320330

321331
/// `RingBufferMutIterator` holds a reference to a `RingBuffer` and iterates over it. `index` is the
@@ -358,6 +368,11 @@ mod iter {
358368
None
359369
}
360370
}
371+
372+
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
373+
self.len = self.len - n.min(self.len);
374+
self.next_back()
375+
}
361376
}
362377

363378
impl<'rb, T, RB: RingBuffer<T> + 'rb> Iterator for RingBufferMutIterator<'rb, T, RB> {
@@ -377,6 +392,11 @@ mod iter {
377392
fn size_hint(&self) -> (usize, Option<usize>) {
378393
(self.len, Some(self.len))
379394
}
395+
396+
fn nth(&mut self, n: usize) -> Option<Self::Item> {
397+
self.index = (self.index + n).min(self.len);
398+
self.next()
399+
}
380400
}
381401

382402
/// `RingBufferMutIterator` holds a reference to a `RingBuffer` and iterates over it.

0 commit comments

Comments
 (0)