Skip to content

Commit

Permalink
feat: Allow store collection iterators to be cloned (this enables sta…
Browse files Browse the repository at this point in the history
…ndard Iterator methods like `cycle()`) (#1224)
  • Loading branch information
g4titanx authored Aug 5, 2024
1 parent f0b522f commit 9c15030
Show file tree
Hide file tree
Showing 8 changed files with 56 additions and 2 deletions.
1 change: 1 addition & 0 deletions near-sdk/src/store/free_list/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ fn decrement_count(count: &mut u32) {
}

/// An iterator over elements in the storage bucket. This only yields the occupied entries.
#[derive(Clone)]
pub struct Iter<'a, T>
where
T: BorshDeserialize + BorshSerialize,
Expand Down
2 changes: 1 addition & 1 deletion near-sdk/src/store/free_list/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ where
}

#[near(inside_nearsdk)]
#[derive(Debug)]
#[derive(Debug, Clone)]
enum Slot<T> {
/// Represents a filled cell of a value in the collection.
Occupied(T),
Expand Down
1 change: 1 addition & 0 deletions near-sdk/src/store/iterable_map/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ where
/// An iterator over elements of a [`IterableMap`].
///
/// This `struct` is created by the `iter` method on [`IterableMap`].
#[derive(Clone)]
pub struct Iter<'a, K, V, H>
where
K: BorshSerialize + Ord + BorshDeserialize,
Expand Down
1 change: 1 addition & 0 deletions near-sdk/src/store/iterable_set/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ where
/// See its documentation for more.
///
/// [`iter`]: IterableSet::iter
#[derive(Clone)]
pub struct Iter<'a, T>
where
T: BorshSerialize + Ord + BorshDeserialize,
Expand Down
3 changes: 3 additions & 0 deletions near-sdk/src/store/tree_map/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ where
/// An iterator over elements of a [`TreeMap`], in sorted order.
///
/// This `struct` is created by the `iter` method on [`TreeMap`].
#[derive(Clone)]
pub struct Iter<'a, K, V, H>
where
K: BorshSerialize + Ord + BorshDeserialize,
Expand Down Expand Up @@ -408,6 +409,7 @@ where
/// An iterator over the keys of a [`TreeMap`], in sorted order.
///
/// This `struct` is created by the `keys` method on [`TreeMap`].
#[derive(Clone)]
pub struct Keys<'a, K: 'a>
where
K: BorshSerialize + BorshDeserialize + Ord,
Expand Down Expand Up @@ -676,6 +678,7 @@ where
/// An iterator over the values of a [`TreeMap`], in order by key.
///
/// This `struct` is created by the `values` method on [`TreeMap`].
#[derive(Clone)]
pub struct Values<'a, K, V, H>
where
K: BorshSerialize + Ord + BorshDeserialize,
Expand Down
47 changes: 47 additions & 0 deletions near-sdk/src/store/unordered_map/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ where
/// An iterator over elements of a [`UnorderedMap`].
///
/// This `struct` is created by the `iter` method on [`UnorderedMap`].
#[derive(Clone)]
pub struct Iter<'a, K, V, H>
where
K: BorshSerialize + Ord + BorshDeserialize,
Expand Down Expand Up @@ -222,6 +223,7 @@ where
/// An iterator over the keys of a [`UnorderedMap`].
///
/// This `struct` is created by the `keys` method on [`UnorderedMap`].
#[derive(Clone)]
pub struct Keys<'a, K: 'a>
where
K: BorshSerialize + BorshDeserialize,
Expand Down Expand Up @@ -277,6 +279,7 @@ where
/// An iterator over the values of a [`UnorderedMap`].
///
/// This `struct` is created by the `values` method on [`UnorderedMap`].
#[derive(Clone)]
pub struct Values<'a, K, V, H>
where
K: BorshSerialize + Ord + BorshDeserialize,
Expand Down Expand Up @@ -521,3 +524,47 @@ where
Some(self.remove_value(key))
}
}

#[cfg(test)]
mod tests {
use super::*;
use borsh::{BorshDeserialize, BorshSerialize};

#[derive(BorshSerialize, BorshDeserialize, Ord, PartialOrd, Eq, PartialEq, Debug, Clone)]
struct Key(i32);

#[derive(BorshSerialize, BorshDeserialize, Debug, Clone, PartialEq)]
struct Value(String);

#[test]
fn test_unordered_map_iter_clone() {
let mut store = UnorderedMap::new(b'a');

store.insert(Key(1), Value("one".to_string()));
store.insert(Key(2), Value("two".to_string()));
store.insert(Key(3), Value("three".to_string()));

let mut iter = store.iter().cycle();

let mut collected = vec![];
for _ in 0..9 {
if let Some((key, value)) = iter.next() {
collected.push((key.clone(), value.clone()));
}
}

let expected = vec![
(Key(1), Value("one".to_string())),
(Key(2), Value("two".to_string())),
(Key(3), Value("three".to_string())),
(Key(1), Value("one".to_string())),
(Key(2), Value("two".to_string())),
(Key(3), Value("three".to_string())),
(Key(1), Value("one".to_string())),
(Key(2), Value("two".to_string())),
(Key(3), Value("three".to_string())),
];

assert_eq!(collected, expected);
}
}
1 change: 1 addition & 0 deletions near-sdk/src/store/unordered_set/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ where
/// See its documentation for more.
///
/// [`iter`]: UnorderedSet::iter
#[derive(Clone)]
pub struct Iter<'a, T>
where
T: BorshSerialize + Ord + BorshDeserialize,
Expand Down
2 changes: 1 addition & 1 deletion near-sdk/src/store/vec/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use super::{Vector, ERR_INDEX_OUT_OF_BOUNDS};
use crate::env;

/// An iterator over references to each element in the stored vector.
#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct Iter<'a, T>
where
T: BorshSerialize + BorshDeserialize,
Expand Down

0 comments on commit 9c15030

Please sign in to comment.