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.
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
method returns aColumnAccess
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.
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
, 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.
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()),
]);