Skip to content

Commit 1a5e29c

Browse files
committed
storey: container impl docs
1 parent cad01d5 commit 1a5e29c

File tree

5 files changed

+460
-0
lines changed

5 files changed

+460
-0
lines changed

Diff for: docs-test-gen/src/main.rs

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ static TEMPLATES: phf::Map<&'static str, &'static str> = phf_map! {
1212
"ibc-channel" => include_str!("../templates/ibc-channel.tpl"),
1313
"ibc-packet" => include_str!("../templates/ibc-packet.tpl"),
1414
"storage" => include_str!("../templates/storage.tpl"),
15+
"storey-container-impl" => include_str!("../templates/storey-container-impl.tpl"),
1516
"sylvia-storey-contract" => include_str!("../templates/sylvia/storey_contract.tpl"),
1617
"sylvia-cw-storage-contract" => include_str!("../templates/sylvia/cw_storage_contract.tpl"),
1718
"sylvia-empty" => include_str!("../templates/sylvia/empty.tpl"),

Diff for: docs-test-gen/templates/storey-container-impl.tpl

+200
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
#![allow(
2+
unexpected_cfgs,
3+
dead_code,
4+
unused_variables,
5+
unused_imports,
6+
clippy::new_without_default
7+
)]
8+
use cosmwasm_schema::cw_serde;
9+
use cosmwasm_std::*;
10+
use storey::containers::{IterableStorable, NonTerminal, Storable};
11+
use storey::storage::{IntoStorage, StorageBranch};
12+
13+
mod users {
14+
use super::*;
15+
16+
use cw_storage_plus::{index_list, IndexedMap, MultiIndex, UniqueIndex};
17+
18+
pub type Handle = String;
19+
20+
#[cw_serde]
21+
pub struct User {
22+
pub handle: String,
23+
pub country: String,
24+
}
25+
26+
pub struct ExampleUsers {
27+
pub alice: User,
28+
pub bob: User,
29+
}
30+
31+
pub fn example_users() -> ExampleUsers {
32+
ExampleUsers {
33+
alice: User {
34+
handle: "alice".to_string(),
35+
country: "Wonderland".to_string(),
36+
},
37+
bob: User {
38+
handle: "bob".to_string(),
39+
country: "USA".to_string(),
40+
},
41+
}
42+
}
43+
44+
#[index_list(User)]
45+
pub struct UserIndexes<'a> {
46+
pub handle_ix: UniqueIndex<'a, Handle, User, Addr>,
47+
pub country_ix: MultiIndex<'a, String, User, Addr>,
48+
}
49+
50+
pub fn user_indexes() -> UserIndexes<'static> {
51+
user_indexes_custom("u", "uh", "uc")
52+
}
53+
54+
pub fn user_indexes_custom(
55+
ns: &'static str,
56+
handle_prefix: &'static str,
57+
country_prefix: &'static str,
58+
) -> UserIndexes<'static> {
59+
UserIndexes {
60+
handle_ix: UniqueIndex::new(|user| user.handle.clone(), handle_prefix),
61+
country_ix: MultiIndex::new(|_pk, user| user.country.clone(), ns, country_prefix),
62+
}
63+
}
64+
}
65+
66+
fn advance_height(env: &mut Env, blocks: u64) {
67+
env.block.height += blocks;
68+
}
69+
70+
struct MyMap<V> {
71+
prefix: u8,
72+
phantom: std::marker::PhantomData<V>,
73+
}
74+
75+
impl<V> MyMap<V>
76+
where
77+
V: Storable,
78+
{
79+
pub const fn new(prefix: u8) -> Self {
80+
Self {
81+
prefix,
82+
phantom: std::marker::PhantomData,
83+
}
84+
}
85+
86+
pub fn access<F, S>(&self, storage: F) -> MyMapAccess<V, StorageBranch<S>>
87+
where
88+
(F,): IntoStorage<S>,
89+
{
90+
let storage = (storage,).into_storage();
91+
Self::access_impl(StorageBranch::new(storage, vec![self.prefix]))
92+
}
93+
}
94+
95+
pub struct MyMapAccess<V, S> {
96+
storage: S,
97+
phantom: std::marker::PhantomData<V>,
98+
}
99+
100+
impl<V> Storable for MyMap<V>
101+
where
102+
V: Storable,
103+
{
104+
type Kind = NonTerminal;
105+
type Accessor<S> = MyMapAccess<V, S>;
106+
107+
fn access_impl<S>(storage: S) -> MyMapAccess<V, S> {
108+
MyMapAccess {
109+
storage,
110+
phantom: std::marker::PhantomData,
111+
}
112+
}
113+
}
114+
115+
impl<V> IterableStorable for MyMap<V>
116+
where
117+
V: IterableStorable,
118+
<V as IterableStorable>::KeyDecodeError: std::fmt::Display,
119+
{
120+
type Key = (u32, V::Key);
121+
type KeyDecodeError = ();
122+
type Value = V::Value;
123+
type ValueDecodeError = V::ValueDecodeError;
124+
125+
fn decode_key(key: &[u8]) -> Result<Self::Key, ()> {
126+
todo!()
127+
}
128+
129+
fn decode_value(value: &[u8]) -> Result<Self::Value, Self::ValueDecodeError> {
130+
V::decode_value(value)
131+
}
132+
}
133+
134+
impl<V, S> MyMapAccess<V, S>
135+
where
136+
V: Storable,
137+
{
138+
pub fn entry(&self, key: u32) -> V::Accessor<StorageBranch<&S>> {
139+
let key = key.to_be_bytes().to_vec();
140+
141+
V::access_impl(StorageBranch::new(&self.storage, key))
142+
}
143+
144+
pub fn entry_mut(&mut self, key: u32) -> V::Accessor<StorageBranch<&mut S>> {
145+
let key = key.to_be_bytes().to_vec();
146+
147+
V::access_impl(StorageBranch::new(&mut self.storage, key))
148+
}
149+
}
150+
151+
#[test]
152+
fn doctest() {
153+
#[allow(unused_variables, unused_mut)]
154+
let mut storage = cosmwasm_std::testing::MockStorage::new();
155+
#[allow(unused_mut)]
156+
let mut env = cosmwasm_std::testing::mock_env();
157+
158+
let users = cw_storage_plus::IndexedMap::<Addr, _, _>::new(
159+
"uu",
160+
users::user_indexes_custom("uu", "uuh", "uuc"),
161+
);
162+
163+
let users_data = [
164+
(
165+
Addr::unchecked("aaa"),
166+
users::User {
167+
handle: "alice".to_string(),
168+
country: "Wonderland".to_string(),
169+
},
170+
),
171+
(
172+
Addr::unchecked("bbb"),
173+
users::User {
174+
handle: "bob".to_string(),
175+
country: "USA".to_string(),
176+
},
177+
),
178+
(
179+
Addr::unchecked("ccc"),
180+
users::User {
181+
handle: "carol".to_string(),
182+
country: "UK".to_string(),
183+
},
184+
),
185+
(
186+
Addr::unchecked("ddd"),
187+
users::User {
188+
handle: "dave".to_string(),
189+
country: "USA".to_string(),
190+
},
191+
),
192+
];
193+
194+
for (addr, user) in users_data {
195+
users.save(&mut storage, addr, &user).unwrap();
196+
}
197+
198+
#[rustfmt::skip]
199+
{{code}}
200+
}

Diff for: src/pages/storey/container-impl.mdx

+12
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,15 @@ tags: ["storey"]
55
import { Callout } from "nextra/components";
66

77
# Implementing new containers
8+
9+
Storey provides a set of built-in containers, but you're not limited to just those. For special
10+
needs, you can go ahead and create your own containers that will play along nicely with the rest of
11+
the Storey "ecosystem". If it's appropriate, your container could for example allow for nesting
12+
other containers - like [`Map`].
13+
14+
In this section, you will find examples of custom containers with their full code.
15+
16+
# Guides
17+
18+
- [MyMap](container-impl/my-map)
19+

Diff for: src/pages/storey/container-impl/_meta.js

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export default {
2+
"my-map": "MyMap",
3+
};

0 commit comments

Comments
 (0)