Skip to content

Commit

Permalink
Merge pull request #23 from CosmWasm/storage-plus-containers
Browse files Browse the repository at this point in the history
`storage-plus`: containers
  • Loading branch information
uint authored Jun 17, 2024
2 parents fb23899 + b367e1c commit a49fa44
Show file tree
Hide file tree
Showing 11 changed files with 351 additions and 17 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/doc-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ jobs:
cargo update -p cosmwasm-schema
cargo update -p cosmwasm-std
cargo update -p cw2
cargo update -p cw-storage-plus
cargo update -p serde
- uses: Swatinem/rust-cache@v2
with:
workspaces: |
Expand Down
1 change: 1 addition & 0 deletions docs-test-gen/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions docs-test-gen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ cosmwasm-std = { version = "*", features = ["stargate", "staking", "cosmwasm_2_0
sha2 = "0.10.8"
cosmos-sdk-proto = { version = "0.21.1", default-features = false } # Used in IBC code
cw-storage-plus = "*"
serde = "*"
1 change: 1 addition & 0 deletions docs-test-gen/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ static TEMPLATES: phf::Map<&'static str, &'static str> = phf_map! {
"execute" => include_str!("../templates/execute.tpl"),
"instantiate-spec" => include_str!("../templates/instantiate-spec.tpl"),
"ibc-channel" => include_str!("../templates/ibc-channel.tpl"),
"storage" => include_str!("../templates/storage.tpl"),
};

#[inline]
Expand Down
15 changes: 15 additions & 0 deletions docs-test-gen/templates/storage.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#[allow(unused_imports)]
mod imports {
pub use cosmwasm_std::*;
pub use cosmwasm_schema::cw_serde;
}

#[allow(unused_imports)]
use imports::*;

#[test]
fn doctest() {
#[allow(unused_mut)]
let mut storage = cosmwasm_std::testing::MockStorage::new();
{{code}}
}
4 changes: 4 additions & 0 deletions scripts/watch.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env bash
set -o nounset -o pipefail

inotifywait -e modify,move,create,delete --recursive --monitor --format "%e %w%f" src | while read changed; do echo $changed; scripts/test-rust.sh; done
1 change: 0 additions & 1 deletion src/pages/cw-storage-plus/_meta.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{
"basics": "Basics",
"containers": "Containers",
"iteration": "Iteration",
"snapshots": "Snapshots",
"multi-indexes": "Multi index collections"
}
101 changes: 99 additions & 2 deletions src/pages/cw-storage-plus/containers/deque.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,104 @@
import { Callout } from "nextra/components";

# `Deque`

## Overview
A `Deque` imitates a traditional double-ended queue. This collection is designed
for efficient pushes and pops from either the beginning or end, but not for
insertions/deletions from the middle. It can easily serve as a queue or stack.

The main operations available here are [`push_back`], [`push_front`],
[`pop_back`], and [`pop_front`]. It is also possible to check the [`len`]gth of
the deque, [`get`] an element by index, and [`iter`]ate over the elements.

[`push_back`]:
https://docs.rs/cw-storage-plus/latest/cw_storage_plus/struct.Deque.html#method.push_back
[`push_front`]:
https://docs.rs/cw-storage-plus/latest/cw_storage_plus/struct.Deque.html#method.push_front
[`pop_back`]:
https://docs.rs/cw-storage-plus/latest/cw_storage_plus/struct.Deque.html#method.pop_back
[`pop_front`]:
https://docs.rs/cw-storage-plus/latest/cw_storage_plus/struct.Deque.html#method.pop_front
[`len`]:
https://docs.rs/cw-storage-plus/latest/cw_storage_plus/struct.Deque.html#method.len
[`get`]:
https://docs.rs/cw-storage-plus/latest/cw_storage_plus/struct.Deque.html#method.get
[`iter`]:
https://docs.rs/cw-storage-plus/latest/cw_storage_plus/struct.Deque.html#method.iter

<Callout type="warning">
The maximum capacity of a `Deque` is `u32::MAX - 1` elements. Trying to push
more elements is considered Undefined Behavior💀.
</Callout>

More information can be found in the
[API docs](https://docs.rs/cw-storage-plus/latest/cw_storage_plus/struct.Deque.html).

## Examples

### ?
### Pushing and popping

```rust template="storage"
use cw_storage_plus::Deque;

let deque: Deque<u32> = Deque::new("d");

deque.push_back(&mut storage, &2).unwrap();
deque.push_back(&mut storage, &3).unwrap();
deque.push_front(&mut storage, &1).unwrap();

// at this point, we have [1, 2, 3]

assert_eq!(deque.pop_back(&mut storage).unwrap(), Some(3));
assert_eq!(deque.pop_front(&mut storage).unwrap(), Some(1));
assert_eq!(deque.pop_back(&mut storage).unwrap(), Some(2));
assert_eq!(deque.pop_back(&mut storage).unwrap(), None);
```

### Checking length

```rust template="storage"
use cw_storage_plus::Deque;

let deque: Deque<u32> = Deque::new("d");

assert_eq!(deque.len(&storage).unwrap(), 0);

deque.push_back(&mut storage, &1).unwrap();
deque.push_back(&mut storage, &2).unwrap();

assert_eq!(deque.len(&storage).unwrap(), 2);
```

### Getting an element by index

```rust template="storage"
use cw_storage_plus::Deque;

let deque: Deque<u32> = Deque::new("d");

deque.push_back(&mut storage, &1).unwrap();
deque.push_back(&mut storage, &2).unwrap();

assert_eq!(deque.get(&storage, 0).unwrap(), Some(1));
assert_eq!(deque.get(&storage, 1).unwrap(), Some(2));
assert_eq!(deque.get(&storage, 2).unwrap(), None);
```

### Iterating over elements

```rust template="storage"
use cw_storage_plus::Deque;

let deque: Deque<u32> = Deque::new("d");

deque.push_back(&mut storage, &2).unwrap();
deque.push_back(&mut storage, &3).unwrap();
deque.push_front(&mut storage, &1).unwrap();

let mut iter = deque.iter(&storage).unwrap();

assert_eq!(iter.next(), Some(Ok(1)));
assert_eq!(iter.next(), Some(Ok(2)));
assert_eq!(iter.next(), Some(Ok(3)));
assert_eq!(iter.next(), None);
```
77 changes: 74 additions & 3 deletions src/pages/cw-storage-plus/containers/item.mdx
Original file line number Diff line number Diff line change
@@ -1,9 +1,80 @@
# `Item`

## Overview
An `Item` is a container that stores a single value under a specific key in
storage.

## Examples
Merely constructing the `Item` object does not commit anything to storage. If an
`Item` has never been written to before (or the value has been
[removed](https://docs.rs/cw-storage-plus/latest/cw_storage_plus/struct.Item.html#method.remove)),
it will be empty.

Under the hood, values are serialized with [`serde`](https://serde.rs/) and
[`serde_json_wasm`](https://docs.rs/serde_json_wasm/).

Use `save` to write to an `Item`.

Use `load` to read from the `Item`, producing an error if the `Item` is empty or
if deserialization fails.

Use `may_load` if you want to explicitly handle the possibility the `Item` is
empty - this will produce an
[`StdError`](https://docs.rs/cosmwasm-std/latest/cosmwasm_std/enum.StdError.html)
if deserialization fails, but produce an `Ok(None)` if it is empty.

More information can be found in the
[API docs](https://docs.rs/cw-storage-plus/latest/cw_storage_plus/struct.Item.html).

## Usage examples

### Saving an admin address

### Saving a config structure
```rust template="storage"
use cw_storage_plus::Item;

let admin: Item<String> = Item::new("a");
assert_eq!(admin.may_load(&storage).unwrap(), None);

admin.save(&mut storage, &"some_address".to_string()).unwrap();
assert_eq!(admin.load(&storage).unwrap(), "some_address");
```

### Maintaining a config structure

```rust template="storage"
use cw_storage_plus::Item;
use serde::{Serialize, Deserialize};

#[cw_serde]
struct Config {
admin: String,
interest_rate: Decimal,
}

let cfg = Config {
admin: "some_address".to_string(),
interest_rate: Decimal::percent(5),
};
let cfg_storage: Item<Config> = Item::new("c");
cfg_storage.save(&mut storage, &cfg).unwrap();

assert_eq!(cfg_storage.load(&storage).unwrap(), cfg);
```

### Default values

Sometimes you might like to read a value, but if it may have never been set, you
want to provide a default. This is a common pattern for counters or other
numeric values.

```rust template="storage"
use cw_storage_plus::Item;

let counter: Item<u128> = Item::new("t");

let mut total = counter.may_load(&storage).unwrap().unwrap_or(0);

assert_eq!(total, 0);
total += 1;

counter.save(&mut storage, &total).unwrap();
```
Loading

0 comments on commit a49fa44

Please sign in to comment.