Skip to content

Commit

Permalink
storey: document Column
Browse files Browse the repository at this point in the history
  • Loading branch information
uint committed Dec 9, 2024
1 parent 68979d0 commit 5b53b75
Showing 1 changed file with 129 additions and 0 deletions.
129 changes: 129 additions & 0 deletions src/pages/storey/containers/column.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,132 @@ tags: ["storey", "containers"]
import { Callout } from "nextra/components";

# Column

A [`Column`] is a collection of items indexed by auto-incrementing `u32` keys.
This might sound similar to a relational database table; in fact, it is a good analogy.

A [`Column`] makes it efficient to push items to it and access the last element.

<Callout>
It should be noted that in a future version indexing will start at `1`, not `0`.

This change will also break existing contracts that rely on the current `Column` implementation!
</Callout>

## Examples

### Storing a message log

Let's say you want to store a log of messages. You can do this with a `Column<String>`.

```rust template="storage" showLineNumbers {6,8,10,12}
use cw_storey::containers::Column;
use cw_storey::CwStorage;

const MESSAGES_IX: u8 = 1;

let messages: Column<String> = Column::new(MESSAGES_IX);
let mut cw_storage = CwStorage(&mut storage);
let mut access = messages.access(&mut cw_storage);

access.push(&"Hello, world!".to_string()).unwrap();

assert_eq!(access.get(0).unwrap(), Some("Hello, world!".to_string()));
```

- _line 6:_ Here we construct the `Column` facade. The constructor takes a key, which is the prefix of
the keys in the underlying storage backend.
- _line 8:_ The [`access`] method returns a [`ColumnAccess`] entity, which allows manipulating the column.
- _line 10:_ Here we push a message to the column.
- _line 12:_ We check that the message is stored correctly.

#### Iterating over the messages

As with [`Map`], we can iterate over all messages.

```rust template="storage" showLineNumbers {4, 17}
use cw_storey::containers::{Column, Item};
use cw_storey::CwStorage;

use storey::containers::IterableAccessor as _;

const MESSAGES_IX: u8 = 1;

let messages: Column<String> = Column::new(MESSAGES_IX);
let mut cw_storage = CwStorage(&mut storage);
let mut access = messages.access(&mut cw_storage);

// populate the column
access.push(&"Hello, world!".to_string()).unwrap();
access.push(&"My name is Bob.".to_string()).unwrap();
access.push(&"Hell is empty and all the devils are here.".to_string()).unwrap();

let messages: Vec<_> = access.pairs().collect::<Result<_, _>>().unwrap();

assert_eq!(messages, vec![
(0, "Hello, world!".to_string()),
(1, "My name is Bob.".to_string()),
(2, "Hell is empty and all the devils are here.".to_string()),
]);
```

- _line 4:_ We import the `IterableAccessor` trait to use iteration methods.
- _line 17:_ The `pairs` method produces an iterator
over tuples of `(index, value)`. In this case, we collect the iterator into a `Vec` for ease of making our assertion later.

Similarly to [`Map`], you can use the [`keys`], [`values`], and [`pairs`] methods to iterate over the items.

#### Bounded iteration

If you want to perform bounded iteration, it is possible.
This time you need the [`BoundedIterableAccessor`] trait, and the relevant methods are
[`bounded_pairs`], [`bounded_keys`], and [`bounded_values`].

The following example is the same as the previous one except for the bounds
found in line 17, and the limited results.

<Callout>
Currently, the lower bound is inclusive, and the upper bound is exclusive.

This will change in a future version, where you'll be able to choose between inclusive and exclusive bounds as suits you.
</Callout>

```rust template="storage" showLineNumbers {4, 17}
use cw_storey::containers::{Column, Item};
use cw_storey::CwStorage;

use storey::containers::BoundedIterableAccessor as _;

const MESSAGES_IX: u8 = 1;

let messages: Column<String> = Column::new(MESSAGES_IX);
let mut cw_storage = CwStorage(&mut storage);
let mut access = messages.access(&mut cw_storage);

// populate the column
access.push(&"Hello, world!".to_string()).unwrap();
access.push(&"My name is Bob.".to_string()).unwrap();
access.push(&"Hell is empty and all the devils are here.".to_string()).unwrap();

let messages: Vec<_> = access.bounded_pairs(Some(0), Some(2)).collect::<Result<_, _>>().unwrap();

assert_eq!(messages, vec![
(0, "Hello, world!".to_string()),
(1, "My name is Bob.".to_string()),
]);
```

[`Column`]: https://docs.rs/storey/latest/storey/containers/struct.Column.html
[`access`]: https://docs.rs/storey/latest/storey/containers/struct.Column.html#method.access
[`ColumnAccess`]: https://docs.rs/storey/latest/storey/containers/struct.ColumnAccess.html
[`keys`]: https://docs.rs/storey/latest/storey/containers/struct.ColumnAccess.html#method.keys
[`values`]: https://docs.rs/storey/latest/storey/containers/struct.ColumnAccess.html#method.values
[`pairs`]: https://docs.rs/storey/latest/storey/containers/struct.ColumnAccess.html#method.pairs
[`Map`]: https://docs.rs/storey/latest/storey/containers/struct.Map.html
[`MapAccess`]: https://docs.rs/storey/latest/storey/containers/struct.MapAccess.html
[`ItemAccess`]: https://docs.rs/storey/latest/storey/containers/struct.ItemAccess.html
[`IterableAccessor`]: https://docs.rs/storey/latest/storey/containers/trait.IterableAccessor.html
[`BoundedIterableAccessor`]: https://docs.rs/storey/latest/storey/containers/trait.BoundedIterableAccessor.html
[`bounded_pairs`]: https://docs.rs/storey/latest/storey/containers/trait.BoundedIterableAccessor.html#method.bounded_pairs
[`bounded_keys`]: https://docs.rs/storey/latest/storey/containers/trait.BoundedIterableAccessor.html#method.bounded_keys
[`bounded_values`]: https://docs.rs/storey/latest/storey/containers/trait.BoundedIterableAccessor.html#method.bounded_values

0 comments on commit 5b53b75

Please sign in to comment.