Skip to content

Commit

Permalink
Merge pull request #1838 from CosmWasm/1725-skip-iterator
Browse files Browse the repository at this point in the history
Impl nth for External(Partial)Iterator
  • Loading branch information
chipshort committed Aug 29, 2023
2 parents e24ff62 + 8e4907a commit f8f9598
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 0 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ and this project adheres to
- cosmwasm-vm: Use `wasmparser` for initial validation instead of `parity-wasm`
([#1786])
- cosmwasm-std: Make constructors `Decimal{,256}::{percent,permille,bps}` const
- cosmwasm-std: Use new `db_next_key` import to make `skip` and `nth`
implementation of `range` iterators more efficient. This requires the
`cosmwasm_1_4` feature to be enabled. ([#1838])

[#1667]: https://github.com/CosmWasm/cosmwasm/pull/1667
[#1674]: https://github.com/CosmWasm/cosmwasm/pull/1674
Expand All @@ -46,6 +49,7 @@ and this project adheres to
[#1701]: https://github.com/CosmWasm/cosmwasm/pull/1701
[#1786]: https://github.com/CosmWasm/cosmwasm/pull/1786
[#1793]: https://github.com/CosmWasm/cosmwasm/pull/1793
[#1838]: https://github.com/CosmWasm/cosmwasm/pull/1838

## [1.3.3] - 2023-08-22

Expand Down
32 changes: 32 additions & 0 deletions packages/std/src/imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,15 @@ struct ExternalPartialIterator {
impl Iterator for ExternalPartialIterator {
type Item = Vec<u8>;

/// The default implementation calls `next` repeatedly,
/// which we can do a little more efficiently by using `db_next_key` instead.
/// It is used by `skip`, so it allows cheaper skipping.
#[cfg(feature = "cosmwasm_1_4")]
fn nth(&mut self, n: usize) -> Option<Self::Item> {
skip_iter(self.iterator_id, n);
self.next()
}

fn next(&mut self) -> Option<Self::Item> {
// here we differentiate between the two types
let next_result = match self.partial_type {
Expand Down Expand Up @@ -229,6 +238,15 @@ struct ExternalIterator {
impl Iterator for ExternalIterator {
type Item = Record;

/// The default implementation calls `next` repeatedly,
/// which we can do a little more efficiently by using `db_next_key` instead.
/// It is used by `skip`, so it allows cheaper skipping.
#[cfg(feature = "cosmwasm_1_4")]
fn nth(&mut self, n: usize) -> Option<Self::Item> {
skip_iter(self.iterator_id, n);
self.next()
}

fn next(&mut self) -> Option<Self::Item> {
let next_result = unsafe { db_next(self.iterator_id) };
let kv_region_ptr = next_result as *mut Region;
Expand All @@ -242,6 +260,20 @@ impl Iterator for ExternalIterator {
}
}

/// Helper function to skip `count` elements of an iterator.
#[cfg(all(feature = "iterator", feature = "cosmwasm_1_4"))]
fn skip_iter(iter_id: u32, count: usize) {
for _ in 0..count {
let region = unsafe { db_next_key(iter_id) };
if region == 0 {
// early return
return;
}
// just deallocate the region
unsafe { consume_region(region as *mut Region) };
}
}

/// A stateless convenience wrapper around imports provided by the VM
#[derive(Copy, Clone)]
pub struct ExternalApi {}
Expand Down

0 comments on commit f8f9598

Please sign in to comment.