Skip to content

Commit

Permalink
Add new() function to StorageKey (#5096)
Browse files Browse the repository at this point in the history
## Description

When creating complex storage types, storing of a `StorageKey` is
sometimes needed. In these cases a `new()` function is appropriate.

For example, when we have the following storage block:
```rust
storage {
    name: StorageMap<u64, StorageKey<StorageString>> = StorageMap {},
}
```

In order to store a `StorageString` in a `StorageMap`, the
`StorageKey<StorageString>` annotation is needed.

From there, we can store a `String` by creating a `StorageKey`, storing
a `String` at said key, and then storing the `StorageKey` in the
`StorageMap`:

```rust
let string_key: StorageKey<StorageString> = StorageKey {
    slot: sha256(0),
    offset: 0,
    field_id: sha256(1),
};
string_key.write_slice(String::from_ascii_str("my_name"));
storage.name.insert(0, string_key);
```

The introduction of `new()` would change this to the following:
```rust
let string_key: StorageKey<StorageString> = StorageKey::new(
     sha256(0), 
     0, 
     sha256(1)
);
string_key.write_slice(String::from_ascii_str("my_name"));
storage.name.insert(0, string_key);
```

## Checklist

- [ ] I have linked to any relevant issues.
- [ ] I have commented my code, particularly in hard-to-understand
areas.
- [ ] I have updated the documentation where relevant (API docs, the
reference, and the Sway book).
- [x] I have added tests that prove my fix is effective or that my
feature works.
- [x] I have added (or requested a maintainer to add) the necessary
`Breaking*` or `New Feature` labels where relevant.
- [x] I have done my best to ensure that my PR adheres to [the Fuel Labs
Code Review
Standards](https://github.com/FuelLabs/rfcs/blob/master/text/code-standards/external-contributors.md).
- [x] I have requested a review from the relevant team or maintainers.

---------

Co-authored-by: bitzoic <[email protected]>
  • Loading branch information
bitzoic and bitzoic authored Sep 9, 2023
1 parent 1d0b9a5 commit e00597c
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 21 deletions.
2 changes: 1 addition & 1 deletion sway-lib-core/src/storage.sw
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ pub struct StorageKey<T> {
slot: b256,
/// The assigned offset based on the data structure `T`.
offset: u64,
/// A unqiue identifier.
/// A unique identifier.
field_id: b256,
}
39 changes: 39 additions & 0 deletions sway-lib-std/src/storage/storage_key.sw
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,43 @@ impl<T> StorageKey<T> {
pub fn write(self, value: T) {
write(self.slot, self.offset, value);
}

/// Create a new `StorageKey`.
///
/// # Arguments
///
/// * `slot`: [b256] - The assigned location in storage for the new `StorageKey`.
/// * `offset`: [u64] - The assigned offset based on the data structure `T` for the new `StorageKey`.
/// * `field_id`: [b256] - A unique identifier for the new `StorageKey`.
///
/// # Returns
///
/// * [StorageKey] - The newly create `StorageKey`.
///
/// # Examples
///
/// ```sway
/// use std::{constants::ZERO_B256, hash::sha256};
///
/// fn foo() {
/// let my_key = StorageKey::<u64>::new(ZERO_B256, 0, sha256(ZERO_B256));
/// assert(my_key.slot == ZERO_B256);
/// }
/// ```
pub fn new(slot: b256, offset: u64, field_id: b256) -> Self {
Self {
slot, offset, field_id
}
}
}

#[test]
fn test_storage_key_new() {
use ::constants::ZERO_B256;
use ::assert::assert;

let key = StorageKey::<u64>::new(ZERO_B256, 0, ZERO_B256);
assert(key.slot == ZERO_B256);
assert(key.offset == 0);
assert(key.field_id == ZERO_B256);
}
10 changes: 5 additions & 5 deletions sway-lib-std/src/storage/storage_map.sw
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,11 @@ impl<K, V> StorageKey<StorageMap<K, V>> where K: Hash {
/// }
/// ```
pub fn get(self, key: K) -> StorageKey<V> where K: Hash {
StorageKey {
slot: sha256((key, self.field_id)),
offset: 0,
field_id: sha256((key, self.field_id)),
}
StorageKey::<V>::new(
sha256((key, self.field_id)),
0,
sha256((key, self.field_id))
)
}

/// Clears a value previously stored using a key
Expand Down
30 changes: 15 additions & 15 deletions sway-lib-std/src/storage/storage_vec.sw
Original file line number Diff line number Diff line change
Expand Up @@ -134,11 +134,11 @@ impl<V> StorageKey<StorageVec<V>> {
return None;
}

Some(StorageKey {
slot: sha256((index, self.field_id)),
offset: 0,
field_id: sha256((index, self.field_id)),
})
Some(StorageKey::<V>::new(
sha256((index, self.field_id)),
0,
sha256((index, self.field_id))
))
}

/// Removes the element in the given index and moves all the elements in the following indexes
Expand Down Expand Up @@ -575,11 +575,11 @@ impl<V> StorageKey<StorageVec<V>> {
pub fn first(self) -> Option<StorageKey<V>> {
match read::<u64>(self.field_id, 0).unwrap_or(0) {
0 => None,
_ => Some(StorageKey {
slot: sha256((0, self.field_id)),
offset: 0,
field_id: sha256((0, self.field_id)),
}),
_ => Some(StorageKey::<V>::new(
sha256((0, self.field_id)),
0,
sha256((0, self.field_id))
)),
}
}

Expand Down Expand Up @@ -614,11 +614,11 @@ impl<V> StorageKey<StorageVec<V>> {
pub fn last(self) -> Option<StorageKey<V>> {
match read::<u64>(self.field_id, 0).unwrap_or(0) {
0 => None,
len => Some(StorageKey {
slot: sha256((len - 1, self.field_id)),
offset: 0,
field_id: sha256((0, self.field_id)),
}),
len => Some(StorageKey::<V>::new(
sha256((len - 1, self.field_id)),
0,
sha256((0, self.field_id))
)),
}
}

Expand Down

0 comments on commit e00597c

Please sign in to comment.