Column
A Column
(opens in a new tab) 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
(opens in a new tab) makes it efficient to push items to it and access the last element.
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!
Examples
Storing a message log
Let's say you want to store a log of messages. You can do this with a Column<String>
.
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
(opens in a new tab) method returns aColumnAccess
(opens in a new tab) 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
(opens in a new tab), we can iterate over all messages.
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 aVec
for ease of making our assertion later.
Similarly to Map
(opens in a new tab), you can use the keys
(opens in a new tab), values
(opens in a new tab), and pairs
(opens in a new tab) methods to iterate over
the items.
Bounded iteration
If you want to perform bounded iteration, it is possible. This time you need the
BoundedIterableAccessor
(opens in a new tab) trait, and the relevant methods are bounded_pairs
(opens in a new tab), bounded_keys
(opens in a new tab),
and bounded_values
(opens in a new tab).
The following example is the same as the previous one except for the bounds found in line 17, and the limited results.
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.
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()),
]);