Skip to content

Commit

Permalink
Merge pull request #20 from LukasKalbertodt/iter-opt
Browse files Browse the repository at this point in the history
Implement `size_hint` and `ExactSizeIterator` for all three iterators
  • Loading branch information
LukasKalbertodt authored Jan 7, 2019
2 parents 77d5005 + c3df049 commit 2e278fa
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 13 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

## [Unreleased]

## [0.2.2] - 2019-01-07
### Added
- All three iterators implement `Iterator::size_hint` and `ExactSizeIterator`
now and report the correct length.

## [0.2.1] - 2018-09-26
### Added
- `StableVec::insert_into_hole()`
Expand Down Expand Up @@ -65,7 +70,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Everything.


[Unreleased]: https://github.com/LukasKalbertodt/stable-vec/compare/v0.2.1...HEAD
[Unreleased]: https://github.com/LukasKalbertodt/stable-vec/compare/v0.2.2...HEAD
[0.2.2]: https://github.com/LukasKalbertodt/stable-vec/compare/v0.2.1...v0.2.2
[0.2.1]: https://github.com/LukasKalbertodt/stable-vec/compare/v0.2.0...v0.2.1
[0.2.0]: https://github.com/LukasKalbertodt/stable-vec/compare/v0.1.2...v0.2.0
[0.1.2]: https://github.com/LukasKalbertodt/stable-vec/compare/v0.1.1...v0.1.2
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "stable-vec"
version = "0.2.1"
version = "0.2.2"
authors = ["Lukas Kalbertodt <[email protected]>"]

description = """
Expand Down
58 changes: 47 additions & 11 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -731,7 +731,7 @@ impl<T> StableVec<T> {
/// }
/// ```
pub fn iter(&self) -> Iter<T> {
Iter { sv: self, pos: 0 }
Iter { sv: self, pos: 0, count: self.used_count }
}

/// Returns an iterator over mutable references to the existing elements
Expand Down Expand Up @@ -781,6 +781,7 @@ impl<T> StableVec<T> {
pub fn iter_mut(&mut self) -> IterMut<T> {
IterMut {
deleted: &mut self.deleted,
count: self.used_count,
used_count: &mut self.used_count,
vec_iter: self.data.iter_mut(),
pos: 0,
Expand Down Expand Up @@ -817,6 +818,7 @@ impl<T> StableVec<T> {
Keys {
deleted: &self.deleted,
pos: 0,
count: self.used_count,
}
}

Expand Down Expand Up @@ -884,8 +886,8 @@ impl<T> StableVec<T> {

/// Retains only the elements specified by the given predicate.
///
/// Each element `e` for which `predicate(&e)` returns `false` is removed
/// from the stable vector.
/// Each element `e` for which `should_be_kept(&e)` returns `false` is
/// removed from the stable vector.
///
/// # Example
///
Expand All @@ -896,14 +898,15 @@ impl<T> StableVec<T> {
///
/// assert_eq!(sv, &[2, 4] as &[_]);
/// ```
pub fn retain<P>(&mut self, mut predicate: P)
pub fn retain<P>(&mut self, mut should_be_kept: P)
where
P: FnMut(&T) -> bool,
{
let mut it = self.iter_mut();
while let Some(e) = it.next() {
if !predicate(e) {
it.remove_current();
let mut pos = 0;

while let Some(idx) = next_valid_index(&mut pos, &self.deleted) {
if !should_be_kept(&self[idx]) {
self.remove(idx);
}
}
}
Expand Down Expand Up @@ -1068,16 +1071,28 @@ impl<'a, T> IntoIterator for &'a mut StableVec<T> {
pub struct Iter<'a, T: 'a> {
sv: &'a StableVec<T>,
pos: usize,
count: usize,
}

impl<'a, T: 'a> Iterator for Iter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
next_valid_index(&mut self.pos, &self.sv.deleted)
.map(|i| &self.sv.data[i])
let out = next_valid_index(&mut self.pos, &self.sv.deleted)
.map(|i| &self.sv.data[i]);
if out.is_some() {
self.count -= 1;
}

out
}

fn size_hint(&self) -> (usize, Option<usize>) {
(self.count, Some(self.count))
}
}

impl<T> ExactSizeIterator for Iter<'_, T> {}

/// Iterator over mutable references to the elements of a `StableVec`.
///
/// Use the method [`StableVec::iter_mut()`](struct.StableVec.html#method.iter_mut)
Expand All @@ -1089,6 +1104,7 @@ pub struct IterMut<'a, T: 'a> {
used_count: &'a mut usize,
vec_iter: ::std::slice::IterMut<'a, T>,
pos: usize,
count: usize,
}

impl<'a, T: 'a> IterMut<'a, T> {
Expand Down Expand Up @@ -1124,11 +1140,19 @@ impl<'a, T> Iterator for IterMut<'a, T> {
} else {
// Advance the iterator by one and return current element.
self.pos += 1;
self.count -= 1;
self.vec_iter.next()
}
}

fn size_hint(&self) -> (usize, Option<usize>) {
(self.count, Some(self.count))
}
}

impl<T> ExactSizeIterator for IterMut<'_, T> {}


/// Iterator over all valid indices of a `StableVec`.
///
/// Use the method [`StableVec::keys()`](struct.StableVec.html#method.keys) to
Expand All @@ -1137,15 +1161,27 @@ impl<'a, T> Iterator for IterMut<'a, T> {
pub struct Keys<'a> {
deleted: &'a BitVec,
pos: usize,
count: usize,
}

impl<'a> Iterator for Keys<'a> {
type Item = usize;
fn next(&mut self) -> Option<Self::Item> {
next_valid_index(&mut self.pos, self.deleted)
let out = next_valid_index(&mut self.pos, self.deleted);
if out.is_some() {
self.count -= 1;
}

out
}

fn size_hint(&self) -> (usize, Option<usize>) {
(self.count, Some(self.count))
}
}

impl ExactSizeIterator for Keys<'_> {}

/// Advances the index `pos` while it points to a deleted element. Stops
/// advancing once an existing element is found or the end is reached. In the
/// former case, this element's index is returned; in the latter case, `None`
Expand Down
32 changes: 32 additions & 0 deletions src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,35 @@ fn insert_into_hole_and_grow() {
assert_eq!(sv.num_elements(), 3);
assert_eq!(sv.clone().into_vec(), &['a', 'c', 'd']);
}

#[test]
fn size_hints() {
let mut sv = StableVec::<()>::new();

assert_eq!(sv.iter().size_hint(), (0, Some(0)));
assert_eq!(sv.iter_mut().size_hint(), (0, Some(0)));
assert_eq!(sv.keys().size_hint(), (0, Some(0)));


let mut sv = StableVec::from(&[0, 1, 2, 3, 4]);
sv.remove(1);

macro_rules! check_iter {
($it:expr) => {{
let mut it = $it;
assert_eq!(it.size_hint(), (4, Some(4)));
assert!(it.next().is_some());
assert_eq!(it.size_hint(), (3, Some(3)));
assert!(it.next().is_some());
assert_eq!(it.size_hint(), (2, Some(2)));
assert!(it.next().is_some());
assert_eq!(it.size_hint(), (1, Some(1)));
assert!(it.next().is_some());
assert_eq!(it.size_hint(), (0, Some(0)));
}}
}

check_iter!(sv.iter());
check_iter!(sv.iter_mut());
check_iter!(sv.keys());
}

0 comments on commit 2e278fa

Please sign in to comment.