Skip to content

Commit

Permalink
Merge branch 'main' into EXC-1404-memory-manager-support-freeing-a-me…
Browse files Browse the repository at this point in the history
…mory
  • Loading branch information
dragoljub-duric authored Nov 30, 2023
2 parents 1ee03a1 + 1224081 commit f38bcda
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 10 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

### Added
- Implemented `DoubleEndedIterator` for `Vec`

## [0.5.6] - 2023-07-05

### Fixed
Made `stable_structures::vec::InitError` public again. It was accidentally made private in the previous release.
- Made `stable_structures::vec::InitError` public again. It was accidentally made private in the previous release.

## [0.5.5] - 2023-07-03

Expand Down
45 changes: 37 additions & 8 deletions src/base_vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,10 @@ use crate::{
read_u32, read_u64, safe_write, write_u32, write_u64, Address, GrowFailed, Memory, Storable,
};
use std::borrow::{Borrow, Cow};
use std::cmp::min;
use std::fmt;
use std::marker::PhantomData;
use std::ops::Range;

const LAYOUT_VERSION: u8 = 1;
/// The offset where the user data begins.
Expand Down Expand Up @@ -227,7 +229,10 @@ impl<T: Storable, M: Memory> BaseVec<T, M> {
Iter {
vec: self,
buf: vec![],
pos: 0,
range: Range {
start: 0,
end: self.len(),
},
}
}

Expand Down Expand Up @@ -346,7 +351,7 @@ where
{
vec: &'a BaseVec<T, M>,
buf: std::vec::Vec<u8>,
pos: u64,
range: Range<u64>,
}

impl<T, M> Iterator for Iter<'_, T, M>
Expand All @@ -357,29 +362,53 @@ where
type Item = T;

fn next(&mut self) -> Option<T> {
if self.vec.len() <= self.pos {
if self.range.is_empty() || self.vec.len() <= self.range.start {
return None;
}

self.vec.read_entry_to(self.pos, &mut self.buf);
self.pos = self.pos.saturating_add(1);
self.vec.read_entry_to(self.range.start, &mut self.buf);
self.range.start = self.range.start.saturating_add(1);
Some(T::from_bytes(Cow::Borrowed(&self.buf)))
}

fn size_hint(&self) -> (usize, Option<usize>) {
(self.vec.len().saturating_sub(self.pos) as usize, None)
(
min(self.vec.len(), self.range.end).saturating_sub(self.range.start) as usize,
None,
)
}

fn count(self) -> usize {
let n = self.vec.len().saturating_sub(self.pos);
let n = self.vec.len().saturating_sub(self.range.start);
if n > usize::MAX as u64 {
panic!("The number of items in the vec {n} does not fit into usize");
}
n as usize
}

fn nth(&mut self, n: usize) -> Option<T> {
self.pos = self.pos.saturating_add(n as u64);
self.range.start = self.range.start.saturating_add(n as u64);
self.next()
}
}

impl<T, M> DoubleEndedIterator for Iter<'_, T, M>
where
T: Storable,
M: Memory,
{
fn next_back(&mut self) -> Option<Self::Item> {
if self.range.is_empty() || self.vec.len() < self.range.end {
return None;
}

self.vec.read_entry_to(self.range.end - 1, &mut self.buf);
self.range.end = self.range.end.saturating_sub(1);
Some(T::from_bytes(Cow::Borrowed(&self.buf)))
}

fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
self.range.end = self.range.end.saturating_sub(n as u64);
self.next_back()
}
}
2 changes: 1 addition & 1 deletion src/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ impl<T: Storable, M: Memory> Vec<T, M> {
self.0.pop()
}

pub fn iter(&self) -> impl Iterator<Item = T> + '_ {
pub fn iter(&self) -> impl DoubleEndedIterator<Item = T> + '_ {
self.0.iter()
}

Expand Down
28 changes: 28 additions & 0 deletions src/vec/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,13 +185,41 @@ fn test_iter() {
assert_eq!(iter.size_hint(), (0, None));
assert_eq!(iter.next(), None);

let mut iter_back = sv.iter();
assert_eq!(iter_back.size_hint(), (3, None));
assert_eq!(iter_back.next_back(), Some(3));
assert_eq!(iter_back.size_hint(), (2, None));
assert_eq!(iter_back.next_back(), Some(2));
assert_eq!(iter_back.size_hint(), (1, None));
assert_eq!(iter_back.next_back(), Some(1));
assert_eq!(iter_back.size_hint(), (0, None));
assert_eq!(iter_back.next_back(), None);

let mut iter_mixed = sv.iter();
assert_eq!(iter_mixed.size_hint(), (3, None));
assert_eq!(iter_mixed.next_back(), Some(3));
assert_eq!(iter_mixed.size_hint(), (2, None));
assert_eq!(iter_mixed.next(), Some(1));
assert_eq!(iter_mixed.size_hint(), (1, None));
assert_eq!(iter_mixed.next_back(), Some(2));
assert_eq!(iter_mixed.size_hint(), (0, None));
assert_eq!(iter_mixed.next(), None);
assert_eq!(iter_mixed.next_back(), None);

assert_eq!(sv.iter().nth(0), Some(1));
assert_eq!(sv.iter().nth(1), Some(2));
assert_eq!(sv.iter().nth(2), Some(3));
assert_eq!(sv.iter().nth(3), None);
assert_eq!(sv.iter().nth(4), None);
assert_eq!(sv.iter().nth(usize::MAX), None);

assert_eq!(sv.iter().nth_back(0), Some(3));
assert_eq!(sv.iter().nth_back(1), Some(2));
assert_eq!(sv.iter().nth_back(2), Some(1));
assert_eq!(sv.iter().nth_back(3), None);
assert_eq!(sv.iter().nth_back(4), None);
assert_eq!(sv.iter().nth_back(usize::MAX), None);

assert_eq!(sv.iter().count(), 3);
assert_eq!(sv.iter().count(), 3);
assert_eq!(sv.iter().skip(1).count(), 2);
Expand Down

0 comments on commit f38bcda

Please sign in to comment.