Skip to content

Commit 648b2f0

Browse files
committed
* Changing the .read() method for StorageHandle to unwrap internally
* Added `try_read()` that behaves like `read` but returns an `Option` * Changed `get` in `StorageMap` to return a `StorageHandle` instead of the value directly.
1 parent 80fff41 commit 648b2f0

File tree

5 files changed

+113
-113
lines changed

5 files changed

+113
-113
lines changed

sway-lib-std/src/experimental/storage.sw

Lines changed: 49 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use core::experimental::storage::StorageHandle;
1111
///
1212
/// * `key` - The storage slot at which the variable will be stored.
1313
/// * `value` - The value to be stored.
14-
/// * `offset` - An offset, in words, from the beginning of slot at `key`, at which `value` should
14+
/// * `offset` - An offset, in words, from the beginning of slot at `key`, at which `value` should
1515
/// be stored.
1616
///
1717
/// ### Examples
@@ -46,16 +46,16 @@ pub fn write<T>(key: b256, offset: u64, value: T) {
4646
let _ = __state_store_quad(key, padded_value, number_of_slots);
4747
}
4848

49-
/// Reads a value of type `T` starting at the location specified by `key` and `offset`. If the
49+
/// Reads a value of type `T` starting at the location specified by `key` and `offset`. If the
5050
/// value crosses the boundary of a storage slot, reading continues at the following slot.
5151
///
52-
/// Returns `Option(value)` if a the storage slots read were valid and contain `value`.
52+
/// Returns `Option(value)` if a the storage slots read were valid and contain `value`.
5353
/// Otherwise, return `None`.
5454
///
5555
/// ### Arguments
5656
///
5757
/// * `key` - The storage slot to load the value from.
58-
/// * `offset` - An offset, in words, from the start of slot at `key`, from which the value should
58+
/// * `offset` - An offset, in words, from the start of slot at `key`, from which the value should
5959
/// be read.
6060
///
6161
/// ### Examples
@@ -113,10 +113,38 @@ pub fn clear<T>(key: b256) -> bool {
113113
}
114114

115115
impl<T> StorageHandle<T> {
116-
/// Reads a value of type `T` starting at the location specified by `self`. If the value
116+
/// Reads a value of type `T` starting at the location specified by `self`. If the value
117117
/// crosses the boundary of a storage slot, reading continues at the following slot.
118118
///
119-
/// Returns `Option(value)` if a the storage slots read were valid and contain `value`.
119+
/// Returns the value previously stored if a the storage slots read were
120+
/// valid and contain `value`. Panics otherwise.
121+
///
122+
/// ### Arguments
123+
///
124+
/// None
125+
///
126+
/// ### Examples
127+
///
128+
/// ```sway
129+
/// fn foo() {
130+
/// let r: StorageHandle<u64> = StorageHandle {
131+
/// key: 0x0000000000000000000000000000000000000000000000000000000000000000,
132+
/// offset: 2,
133+
/// };
134+
///
135+
/// // Reads the third word from storage slot with key 0x000...0
136+
/// let x:u64 = r.read();
137+
/// }
138+
/// ```
139+
#[storage(read)]
140+
pub fn read(self) -> T {
141+
read::<T>(self.key, self.offset).unwrap()
142+
}
143+
144+
/// Reads a value of type `T` starting at the location specified by `self`. If the value
145+
/// crosses the boundary of a storage slot, reading continues at the following slot.
146+
///
147+
/// Returns `Option(value)` if a the storage slots read were valid and contain `value`.
120148
/// Otherwise, return `None`.
121149
///
122150
/// ### Arguments
@@ -129,17 +157,19 @@ impl<T> StorageHandle<T> {
129157
/// fn foo() {
130158
/// let r: StorageHandle<u64> = StorageHandle {
131159
/// key: 0x0000000000000000000000000000000000000000000000000000000000000000,
132-
/// offset: 2,
160+
/// offset: 2,
133161
/// };
134-
/// let x = r.read(); // Reads the third word from storage slot with key 0x000...0
162+
///
163+
/// // Reads the third word from storage slot with key 0x000...0
164+
/// let x:Option<u64> = r.try_read();
135165
/// }
136166
/// ```
137167
#[storage(read)]
138-
pub fn read(self) -> Option<T> {
168+
pub fn try_read(self) -> Option<T> {
139169
read(self.key, self.offset)
140170
}
141171

142-
/// Writes a value of type `T` starting at the location specified by `self`. If the value
172+
/// Writes a value of type `T` starting at the location specified by `self`. If the value
143173
/// crosses the boundary of a storage slot, writing continues at the following slot.
144174
///
145175
/// ### Arguments
@@ -152,7 +182,7 @@ impl<T> StorageHandle<T> {
152182
/// fn foo() {
153183
/// let r: StorageHandle<u64> = StorageHandle {
154184
/// key: 0x0000000000000000000000000000000000000000000000000000000000000000,
155-
/// offset: 2,
185+
/// offset: 2,
156186
/// };
157187
/// let x = r.write(42); // Writes 42 at the third word of storage slot with key 0x000...0
158188
/// }
@@ -195,10 +225,8 @@ impl<K, V> StorageMap<K, V> {
195225
write::<V>(key, 0, value);
196226
}
197227

198-
/// Retrieves a value previously stored using a key.
199-
///
200-
/// If no value was previously stored at `key`, `Option::None` is returned. Otherwise,
201-
/// `Option::Some(value)` is returned, where `value` is the value stored at `key`.
228+
/// Retrieves the `StorageHandle` that describes the raw location in storage of the value
229+
/// stored at `key`, regardless of whether a value is actually stored at that location or not.
202230
///
203231
/// ### Arguments
204232
///
@@ -215,14 +243,16 @@ impl<K, V> StorageMap<K, V> {
215243
/// let key = 5_u64;
216244
/// let value = true;
217245
/// storage.map.insert(key, value);
218-
/// let retrieved_value = storage.map.get(key).unwrap();
246+
/// let retrieved_value = storage.map.get(key).read();
219247
/// assert(value == retrieved_value);
220248
/// }
221249
/// ```
222250
#[storage(read)]
223-
pub fn get(self: StorageHandle<Self>, key: K) -> Option<V> {
224-
let key = sha256((key, self.key));
225-
read::<V>(key, 0)
251+
pub fn get(self: StorageHandle<Self>, key: K) -> StorageHandle<V> {
252+
StorageHandle {
253+
key: sha256((key, self.key)),
254+
offset: 0,
255+
}
226256
}
227257

228258
/// Clears a value previously stored using a key

test/src/sdk-harness/test_projects/experimental_storage/mod.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -156,10 +156,3 @@ async fn maps_in_struct_access() {
156156
(None, None)
157157
);
158158
}
159-
160-
#[tokio::test]
161-
async fn maps_in_map_access() {
162-
let methods = test_experimental_storage_instance().await.methods();
163-
164-
methods.map_in_map_access().call().await.unwrap();
165-
}

test/src/sdk-harness/test_projects/experimental_storage/src/main.sw

Lines changed: 24 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@ storage {
8080
z: 0,
8181
w: 0,
8282
},
83-
map_in_map: StorageMap<u64, StorageHandle<StorageMap<u64, u64>>> = StorageMap {},
8483
}
8584

8685
abi ExperimentalStorageTest {
@@ -107,23 +106,20 @@ abi ExperimentalStorageTest {
107106

108107
#[storage(read, write)]
109108
fn map_in_struct_write(key: (u64, u64), value: (u64, u64));
110-
111-
#[storage(read, write)]
112-
fn map_in_map_access();
113109
}
114110

115111
impl ExperimentalStorageTest for Contract {
116112
#[storage(read, write)]
117113
fn write_and_read_u64(input: u64) -> u64 {
118114
let r = storage.x;
119115
r.write(input);
120-
r.read().unwrap()
116+
r.read()
121117
}
122118

123119
#[storage(read, write)]
124120
fn write_and_read_b256(input: b256) -> b256 {
125121
storage.y.write(input);
126-
storage.y.read().unwrap()
122+
storage.y.read()
127123
}
128124

129125
#[storage(read, write)]
@@ -132,7 +128,7 @@ impl ExperimentalStorageTest for Contract {
132128
// slot where the second half of `simple` is stored
133129
storage.simple.z.write(simple.z);
134130
storage.simple.b.write(simple.b);
135-
storage.simple.read().unwrap()
131+
storage.simple.read()
136132
}
137133

138134
#[storage(read, write)]
@@ -146,17 +142,17 @@ impl ExperimentalStorageTest for Contract {
146142
storage.s.d.write(s.d);
147143

148144
assert(S {
149-
a: storage.s.a.read().unwrap(),
150-
b: storage.s.b.read().unwrap(),
145+
a: storage.s.a.read(),
146+
b: storage.s.b.read(),
151147
c: T {
152-
x: storage.s.c.x.read().unwrap(),
153-
y: storage.s.c.y.read().unwrap(),
148+
x: storage.s.c.x.read(),
149+
y: storage.s.c.y.read(),
154150
z: M {
155-
u: storage.s.c.z.u.read().unwrap(),
156-
v: storage.s.c.z.v.read().unwrap(),
151+
u: storage.s.c.z.u.read(),
152+
v: storage.s.c.z.v.read(),
157153
},
158154
},
159-
d: storage.s.d.read().unwrap(),
155+
d: storage.s.d.read(),
160156
} == s);
161157

162158
// Semi-granular write, granular read
@@ -166,17 +162,17 @@ impl ExperimentalStorageTest for Contract {
166162
storage.s.d.write(s.d);
167163

168164
assert(S {
169-
a: storage.s.a.read().unwrap(),
170-
b: storage.s.b.read().unwrap(),
165+
a: storage.s.a.read(),
166+
b: storage.s.b.read(),
171167
c: T {
172-
x: storage.s.c.x.read().unwrap(),
173-
y: storage.s.c.y.read().unwrap(),
168+
x: storage.s.c.x.read(),
169+
y: storage.s.c.y.read(),
174170
z: M {
175-
u: storage.s.c.z.u.read().unwrap(),
176-
v: storage.s.c.z.v.read().unwrap(),
171+
u: storage.s.c.z.u.read(),
172+
v: storage.s.c.z.v.read(),
177173
},
178174
},
179-
d: storage.s.d.read().unwrap(),
175+
d: storage.s.d.read(),
180176
} == s);
181177

182178
// Granular write, semi-granular read
@@ -188,21 +184,21 @@ impl ExperimentalStorageTest for Contract {
188184
storage.s.d.write(s.d);
189185

190186
assert(S {
191-
a: storage.s.a.read().unwrap(),
192-
b: storage.s.b.read().unwrap(),
193-
c: storage.s.c.read().unwrap(),
194-
d: storage.s.d.read().unwrap(),
187+
a: storage.s.a.read(),
188+
b: storage.s.b.read(),
189+
c: storage.s.c.read(),
190+
d: storage.s.d.read(),
195191
} == s);
196192

197193
// Coarse write and read
198194
storage.s.write(s);
199195

200-
storage.s.read().unwrap()
196+
storage.s.read()
201197
}
202198

203199
#[storage(read)]
204200
fn map_read(key: u64) -> Option<u64> {
205-
storage.map.get(key)
201+
storage.map.get(key).try_read()
206202
}
207203

208204
#[storage(read, write)]
@@ -212,31 +208,12 @@ impl ExperimentalStorageTest for Contract {
212208

213209
#[storage(read)]
214210
fn map_in_struct_read(key: (u64, u64)) -> (Option<u64>, Option<u64>) {
215-
(storage.s2.map0.get(key.0), storage.s2.map1.get(key.1))
211+
(storage.s2.map0.get(key.0).try_read(), storage.s2.map1.get(key.1).try_read())
216212
}
217213

218214
#[storage(read, write)]
219215
fn map_in_struct_write(key: (u64, u64), value: (u64, u64)) {
220216
storage.s2.map0.insert(key.0, value.0);
221217
storage.s2.map1.insert(key.1, value.1);
222218
}
223-
224-
#[storage(read, write)]
225-
fn map_in_map_access() {
226-
storage.map_in_map.insert(0, StorageHandle {
227-
key: std::hash::sha256((storage.map_in_map, 0)),
228-
offset: 0,
229-
});
230-
231-
storage.map_in_map.insert(1, StorageHandle {
232-
key: std::hash::sha256((storage.map_in_map, 1)),
233-
offset: 0,
234-
});
235-
236-
storage.map_in_map.get(0).unwrap().insert(1, 42);
237-
assert(storage.map_in_map.get(0).unwrap().get(1).unwrap() == 42);
238-
239-
storage.map_in_map.get(1).unwrap().insert(1, 24);
240-
assert(storage.map_in_map.get(1).unwrap().get(1).unwrap() == 24);
241-
}
242219
}

test/src/sdk-harness/test_projects/experimental_storage_init/src/main.sw

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -121,27 +121,27 @@ impl ExperimentalStorageInitTest for Contract {
121121
let e2: E = E::A(777);
122122
let string: str[40] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
123123

124-
assert(storage.x.read().unwrap() == x);
125-
assert(storage.y.read().unwrap() == y);
126-
assert(storage.s.read().unwrap() == s);
127-
assert(storage.boolean.read().unwrap() == boolean);
128-
assert(storage.int8.read().unwrap() == int8);
129-
assert(storage.int16.read().unwrap() == int16);
130-
assert(storage.int32.read().unwrap() == int32);
131-
assert(storage.s.x.read().unwrap() == s.x);
132-
assert(storage.s.y.read().unwrap() == s.y);
133-
assert(storage.s.z.read().unwrap() == s.z);
134-
assert(storage.s.t.read().unwrap() == s.t);
135-
assert(storage.s.t.x.read().unwrap() == s.t.x);
136-
assert(storage.s.t.y.read().unwrap() == s.t.y);
137-
assert(storage.s.t.z.read().unwrap() == s.t.z);
138-
assert(storage.s.t.boolean.read().unwrap() == s.t.boolean);
139-
assert(storage.s.t.int8.read().unwrap() == s.t.int8);
140-
assert(storage.s.t.int16.read().unwrap() == s.t.int16);
141-
assert(storage.s.t.int32.read().unwrap() == s.t.int32);
142-
assert(storage.e.read().unwrap() == e);
143-
assert(storage.e2.read().unwrap() == e2);
144-
assert(std::hash::sha256(storage.string.read().unwrap()) == std::hash::sha256(string));
124+
assert(storage.x.read() == x);
125+
assert(storage.y.read() == y);
126+
assert(storage.s.read() == s);
127+
assert(storage.boolean.read() == boolean);
128+
assert(storage.int8.read() == int8);
129+
assert(storage.int16.read() == int16);
130+
assert(storage.int32.read() == int32);
131+
assert(storage.s.x.read() == s.x);
132+
assert(storage.s.y.read() == s.y);
133+
assert(storage.s.z.read() == s.z);
134+
assert(storage.s.t.read() == s.t);
135+
assert(storage.s.t.x.read() == s.t.x);
136+
assert(storage.s.t.y.read() == s.t.y);
137+
assert(storage.s.t.z.read() == s.t.z);
138+
assert(storage.s.t.boolean.read() == s.t.boolean);
139+
assert(storage.s.t.int8.read() == s.t.int8);
140+
assert(storage.s.t.int16.read() == s.t.int16);
141+
assert(storage.s.t.int32.read() == s.t.int32);
142+
assert(storage.e.read() == e);
143+
assert(storage.e2.read() == e2);
144+
assert(std::hash::sha256(storage.string.read()) == std::hash::sha256(string));
145145
true
146146
}
147147
}

0 commit comments

Comments
 (0)