diff --git a/src/pages/storey/containers/column.mdx b/src/pages/storey/containers/column.mdx index 32264d85..a6510c97 100644 --- a/src/pages/storey/containers/column.mdx +++ b/src/pages/storey/containers/column.mdx @@ -5,3 +5,141 @@ 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. + + +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`. + +```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 = 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 = 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::>().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. + + +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. + + + +```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 = 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::>().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/map/struct.Map.html +[`MapAccess`]: https://docs.rs/storey/latest/storey/containers/map/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