Skip to content

Commit cc7b63f

Browse files
committed
storey: finish mymap implementation
1 parent b5274ea commit cc7b63f

File tree

2 files changed

+58
-21
lines changed

2 files changed

+58
-21
lines changed

docs-test-gen/templates/storey-container-impl-iter.tpl

+7-7
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
dead_code,
44
unused_variables,
55
unused_imports,
6-
clippy::new_without_default
6+
clippy::new_without_default,
77
)]
88
use cosmwasm_schema::cw_serde;
99
use cosmwasm_std::*;
@@ -138,19 +138,19 @@ where
138138
<V as IterableStorable>::KeyDecodeError: std::fmt::Display,
139139
{
140140
type Key = (u32, V::Key);
141-
type KeyDecodeError = ();
141+
type KeyDecodeError = String;
142142
type Value = V::Value;
143143
type ValueDecodeError = V::ValueDecodeError;
144144
145-
fn decode_key(key: &[u8]) -> Result<Self::Key, ()> {
145+
fn decode_key(key: &[u8]) -> Result<Self::Key, String> {
146146
if key.len() < 4 {
147-
return Err(());
147+
return Err(String::from("Key too short"));
148148
}
149149

150-
let key_arr = key[0..4].try_into().map_err(|_| ())?;
151-
let this_key = u32::from_le_bytes(key_arr);
150+
let key_arr = key[0..4].try_into().map_err(|e| format!("Invalid key: {}", e))?;
151+
let this_key = u32::from_be_bytes(key_arr);
152152

153-
let rest = V::decode_key(&key[4..]).map_err(|_| ())?;
153+
let rest = V::decode_key(&key[4..]).map_err(|e| e.to_string())?;
154154

155155
Ok((this_key, rest))
156156
}

src/pages/storey/container-impl/my-map.mdx

+51-14
Original file line numberDiff line numberDiff line change
@@ -211,22 +211,22 @@ While we have a functional collection by now, we can't perform iteration yet. In
211211
impl<V> IterableStorable for MyMap<V>
212212
where
213213
V: IterableStorable,
214-
<V as IterableStorable>::KeyDecodeError: std::fmt::Display,
214+
V::KeyDecodeError: std::fmt::Display,
215215
{
216216
type Key = (u32, V::Key);
217-
type KeyDecodeError = ();
217+
type KeyDecodeError = String;
218218
type Value = V::Value;
219219
type ValueDecodeError = V::ValueDecodeError;
220220

221-
fn decode_key(key: &[u8]) -> Result<Self::Key, ()> {
221+
fn decode_key(key: &[u8]) -> Result<Self::Key, String> {
222222
if key.len() < 4 {
223-
return Err(());
223+
return Err(String::from("Key too short"));
224224
}
225225

226-
let key_arr = key[0..4].try_into().map_err(|_| ())?;
227-
let this_key = u32::from_le_bytes(key_arr);
226+
let key_arr = key[0..4].try_into().map_err(|e| format!("Invalid key: {}", e))?;
227+
let this_key = u32::from_be_bytes(key_arr);
228228

229-
let rest = V::decode_key(&key[4..]).map_err(|_| ())?;
229+
let rest = V::decode_key(&key[4..]).map_err(|e| e.to_string())?;
230230

231231
Ok((this_key, rest))
232232
}
@@ -260,22 +260,22 @@ use storey::storage::IterableStorage;
260260
impl<V> IterableStorable for MyMap<V>
261261
where
262262
V: IterableStorable,
263-
<V as IterableStorable>::KeyDecodeError: std::fmt::Display,
263+
V::KeyDecodeError: std::fmt::Display,
264264
{
265265
type Key = (u32, V::Key);
266-
type KeyDecodeError = ();
266+
type KeyDecodeError = String;
267267
type Value = V::Value;
268268
type ValueDecodeError = V::ValueDecodeError;
269269

270-
fn decode_key(key: &[u8]) -> Result<Self::Key, ()> {
270+
fn decode_key(key: &[u8]) -> Result<Self::Key, String> {
271271
if key.len() < 4 {
272-
return Err(());
272+
return Err(String::from("Key too short"));
273273
}
274274

275-
let key_arr = key[0..4].try_into().map_err(|_| ())?;
276-
let this_key = u32::from_le_bytes(key_arr);
275+
let key_arr = key[0..4].try_into().map_err(|e| format!("Invalid key: {}", e))?;
276+
let this_key = u32::from_be_bytes(key_arr);
277277

278-
let rest = V::decode_key(&key[4..]).map_err(|_| ())?;
278+
let rest = V::decode_key(&key[4..]).map_err(|e| e.to_string())?;
279279

280280
Ok((this_key, rest))
281281
}
@@ -318,6 +318,43 @@ let result: Result<Vec<_>, _> = access.values().collect();
318318
assert_eq!(result.unwrap(), vec![100, 200, 300]);
319319
```
320320

321+
This isn't all. What we've also enabled is the ability to iterate over outer containers.
322+
323+
Let's create a regular `Map`, nest our `MyMap` inside it, and see what we can do!
324+
325+
```rust template="storey-container-impl-iter"
326+
use cw_storey::containers::{Item, Map};
327+
use storey::containers::IterableAccessor as _;
328+
329+
const MAP_IX: u8 = 1;
330+
331+
let map: Map<String, MyMap<Item<u32>>> = Map::new(MAP_IX);
332+
let mut access = map.access(&mut storage);
333+
334+
access.entry_mut("alice").entry_mut(1).set(&100).unwrap();
335+
access.entry_mut("alice").entry_mut(2).set(&200).unwrap();
336+
access.entry_mut("bob").entry_mut(1).set(&1100).unwrap();
337+
access.entry_mut("bob").entry_mut(3).set(&1300).unwrap();
338+
339+
let result: Result<Vec<_>, _> = access.pairs().collect();
340+
assert_eq!(result.unwrap(), vec![
341+
(("bob".to_string(), (1, ())), 1100),
342+
(("bob".to_string(), (3, ())), 1300),
343+
(("alice".to_string(), (1, ())), 100),
344+
(("alice".to_string(), (2, ())), 200)
345+
]);
346+
```
347+
348+
We can iterate over everything. Note we didn't have to write any special logic for this nesting in our custom container's implementation.
349+
It's well integrated with Storey simply by implementing a few traits.
350+
351+
<Callout>
352+
We know the parenthesized, nested keys are ugly. We'll eventually try to make this
353+
prettier.
354+
355+
For now, remember this ugliness allows unlimited depth of nested keys, which is pretty cool! Recursion rocks. Sometimes.
356+
</Callout>
357+
321358
[`Item`]: /storey/containers/item
322359
[`Map`]: /storey/containers/map
323360
[`Storable`]: https://docs.rs/storey/latest/storey/containers/trait.Storable.html

0 commit comments

Comments
 (0)