Skip to content

Commit

Permalink
Implement StorageString to std-lib (FuelLabs#4725)
Browse files Browse the repository at this point in the history
## Description

The `String` type has recently been move/introduced to the std-lib. This
is a heap type and does not allow for any storage. The `StorageString`
type allows for storage.

## Checklist

- [x] I have linked to any relevant issues.
- [x] I have commented my code, particularly in hard-to-understand
areas.
- [x] 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 Jul 1, 2023
1 parent 161d889 commit cd63629
Show file tree
Hide file tree
Showing 10 changed files with 426 additions and 0 deletions.
1 change: 1 addition & 0 deletions sway-lib-std/src/storage.sw
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ pub mod storable_slice;
pub mod storage_map;
pub mod storage_vec;
pub mod storage_bytes;
pub mod storage_string;
144 changes: 144 additions & 0 deletions sway-lib-std/src/storage/storage_string.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
library;

use ::bytes::Bytes;
use ::option::Option;
use ::storage::storable_slice::*;
use ::storage::storage_api::read;
use ::string::String;

pub struct StorageString {}

impl StorableSlice<String> for StorageKey<StorageString> {
/// Takes a `String` type and saves the underlying data in storage.
///
/// ### Arguments
///
/// * `string` - The string which will be stored.
///
/// ### Number of Storage Accesses
///
/// * Writes: `2`
///
/// ### Examples
///
/// ```sway
/// storage {
/// stored_string: StorageString = StorageString {}
/// }
///
/// fn foo() {
/// let mut bytes = Bytes::new();
/// bytes.push(5_u8);
/// bytes.push(7_u8);
/// bytes.push(9_u8);
/// let string = String::from(bytes);
///
/// storage.stored_string.write_slice(string);
/// }
/// ```
#[storage(read, write)]
fn write_slice(self, string: String) {
write_slice(self.slot, string.as_raw_slice());
}

/// Constructs a `String` type from storage.
///
/// ### Number of Storage Accesses
///
/// * Reads: `2`
///
/// ### Examples
///
/// ```sway
/// storage {
/// stored_string: StorageString = StorageString {}
/// }
///
/// fn foo() {
/// let mut bytes = Bytes::new();
/// bytes.push(5_u8);
/// bytes.push(7_u8);
/// bytes.push(9_u8);
/// let string = String::from(bytes);
///
/// assert(storage.stored_string.read_slice(key).is_none());
/// storage.stored_string.write_slice(string);
/// let retrieved_string = storage.stored_string.read_slice(key).unwrap();
/// assert(string == retrieved_string);
/// }
/// ```
#[storage(read)]
fn read_slice(self) -> Option<String> {
match read_slice(self.slot) {
Option::Some(slice) => {
Option::Some(String::from(slice))
},
Option::None => Option::None,
}
}

/// Clears a stored `String` in storage.
///
/// ### Number of Storage Accesses
///
/// * Reads: `1`
/// * Clears: `2`
///
/// ### Examples
///
/// ```sway
/// storage {
/// stored_string: StorageString = StorageString {}
/// }
///
/// fn foo() {
/// let mut bytes = Bytes::new();
/// bytes.push(5_u8);
/// bytes.push(7_u8);
/// bytes.push(9_u8);
/// let string = String::from(bytes);
///
/// storage.stored_string.write_slice(string);
///
/// assert(storage.stored_string.read_slice(key).is_some());
/// let cleared = storage.stored_string.clear();
/// assert(cleared);
/// let retrieved_string = storage.stored_string.read_slice(key);
/// assert(retrieved_string.is_none());
/// }
/// ```
#[storage(read, write)]
fn clear(self) -> bool {
clear_slice(self.slot)
}

/// Returns the length of `String` in storage.
///
/// ### Number of Storage Accesses
///
/// * Reads: `1`
///
/// ### Examples
///
/// ```sway
/// storage {
/// stored_string: StorageString = StorageString {}
/// }
///
/// fn foo() {
/// let mut bytes = Bytes::new();
/// bytes.push(5_u8);
/// bytes.push(7_u8);
/// bytes.push(9_u8);
/// let string = String::from(bytes);
///
/// assert(storage.stored_string.len() == 0)
/// storage.stored_string.write_slice(string);
/// assert(storage.stored_string.len() == 3);
/// }
/// ```
#[storage(read)]
fn len(self) -> u64 {
read::<u64>(self.slot, 0).unwrap_or(0)
}
}
5 changes: 5 additions & 0 deletions test/src/sdk-harness/Forc.lock
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,11 @@ name = 'storage_map_nested'
source = 'member'
dependencies = ['std']

[[package]]
name = 'storage_string'
source = 'member'
dependencies = ['std']

[[package]]
name = 'storage_vec_nested'
source = 'member'
Expand Down
1 change: 1 addition & 0 deletions test/src/sdk-harness/Forc.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ members = [
"test_projects/storage_init",
"test_projects/storage_map",
"test_projects/storage_map_nested",
"test_projects/storage_string",
"test_projects/storage_vec_nested",
"test_projects/token_ops",
"test_projects/tx_fields",
Expand Down
1 change: 1 addition & 0 deletions test/src/sdk-harness/test_projects/harness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ mod storage_bytes;
mod storage_init;
mod storage_map;
mod storage_map_nested;
mod storage_string;
mod storage_vec;
mod storage_vec_nested;
mod token_ops;
Expand Down
2 changes: 2 additions & 0 deletions test/src/sdk-harness/test_projects/storage_string/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
out
target
13 changes: 13 additions & 0 deletions test/src/sdk-harness/test_projects/storage_string/Forc.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[[package]]
name = 'core'
source = 'path+from-root-26685F36F0140A56'

[[package]]
name = 'std'
source = 'path+from-root-26685F36F0140A56'
dependencies = ['core']

[[package]]
name = 'storage_string'
source = 'member'
dependencies = ['std']
8 changes: 8 additions & 0 deletions test/src/sdk-harness/test_projects/storage_string/Forc.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[project]
authors = ["Fuel Labs <[email protected]>"]
entry = "main.sw"
license = "Apache-2.0"
name = "storage_string"

[dependencies]
std = { path = "../../../../../sway-lib-std" }
Loading

0 comments on commit cd63629

Please sign in to comment.