Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Strings Library #12

Merged
merged 49 commits into from
Oct 10, 2022
Merged
Show file tree
Hide file tree
Changes from 47 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
c1f05ee
Inital Commit
Aug 3, 2022
1dbabcc
Add base functions
Aug 3, 2022
8a24ca7
Refactor and Rename to match Rust
Aug 3, 2022
80471e3
Tests outline
Aug 3, 2022
2838a0d
Update to string
Aug 3, 2022
de3d3bf
Add len function test
Aug 3, 2022
4b338c7
Add is_empty tests
Aug 3, 2022
e16aeb9
Add clear function tests
Aug 4, 2022
6caec29
Add capacity function tests
Aug 4, 2022
b109dfb
Add new function tests
Aug 4, 2022
e3ab49c
Add push function tests
Aug 4, 2022
352c997
Fix capacity test
Aug 4, 2022
2830e6b
Add with_capacity function tests
Aug 4, 2022
cf8608f
Add some more functions
Aug 4, 2022
f3f195b
First iteration of push_str
Aug 5, 2022
3888a91
Resolve Merge conflicts
Oct 4, 2022
eafb587
Remove functions with relation to str
Oct 4, 2022
d7bf98d
Update function test list to match new string methods
Oct 4, 2022
c37c295
Update empty tests
Oct 4, 2022
0529954
Update len tests
Oct 4, 2022
5033649
Update push test
Oct 4, 2022
b2089bf
Update to use constants for numbers
Oct 4, 2022
83ce059
Add as_bytes test
Oct 4, 2022
54406dc
Add from_utf8 test
Oct 4, 2022
ab7f0a1
Add insert test
Oct 5, 2022
31dfbeb
Add nth test
Oct 5, 2022
bd7f72d
Add test for pop
Oct 5, 2022
11ea781
Add remove test
Oct 5, 2022
73c397b
Update rust SDK for tests
Oct 5, 2022
3c9df9f
Run formatter
Oct 5, 2022
2db5115
Fix bizarre formatting
Oct 5, 2022
2863cd5
Update inline documentation
Oct 5, 2022
d003e41
Update formatting
Oct 5, 2022
63880ab
Remove Forc.lock
Oct 5, 2022
00a417b
Add README.md and SPECIFICATION.md
Oct 5, 2022
83b5602
Fix README link
Oct 5, 2022
eb02cc9
Merge remote-tracking branch 'origin/master' into bitzoic-11
Oct 5, 2022
68afba3
Add how to import to README
Oct 5, 2022
e128a7f
Update code based on suggestions
Oct 6, 2022
d3b5006
Update documentation based on suggestions
Oct 6, 2022
0080b06
Remove warnings and fix instance calls
Oct 6, 2022
33a00f7
Merge remote-tracking branch 'origin/master' into bitzoic-11
Oct 6, 2022
b7e61fd
Update wording of documentation to inform of String's usage of unsafe…
Oct 7, 2022
7db8761
Update incorrect link to source README
Oct 7, 2022
ae7a296
Refactor SDK tests into multiple files
Oct 7, 2022
89d06d6
Add None for nth test
Oct 10, 2022
c79457c
Add EOD to test file
Oct 10, 2022
446f6a7
Update Documentation based on suggestions
Oct 10, 2022
ab46610
Remove unneeded braces from tests
Oct 10, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ These libraries contain helper functions, generalized standards, and other tools
### Libraries

- [Binary Merkle Proof](./sway_libs/src/merkle_proof/) is used to verify Binary Merkle Trees computed off-chain.
- [String](./sway_libs/src/string/) is an interface to implement dynamic length strings that are UTF-8 encoded.

## Using a library

Expand Down
1 change: 1 addition & 0 deletions sway_libs/src/lib.sw
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
library sway_libs;

dep merkle_proof/binary_merkle_proof;
dep string/string;
53 changes: 53 additions & 0 deletions sway_libs/src/string/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Overview

The String library provides an interface to use UTF-8 encoded strings of dynamic length in Sway. The `String` is heap allocated, growable, and not null terminated.

The `String` is stored as vector of bytes. This differs from Sway's built in `str` as the size must not be known at compile time and is not static.
bitzoic marked this conversation as resolved.
Show resolved Hide resolved

For more information please see the [specification](./SPECIFICATION.md).

> **Note** There is currently no way to convert a `str` to a `String`.
bitzoic marked this conversation as resolved.
Show resolved Hide resolved

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If a str cannot be iterated over than I would agree with this note as Braqzen has noted as well. Did you mean perhaps to say an str cannot be casted to a String? IMO you should be able to do let s1: String = String::from("this is an str");

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't believe this will be possible until type constraints are implemented. I think that is part of the declaration engine which afaik @emilyaherbert and @tritao are working on?

bitzoic marked this conversation as resolved.
Show resolved Hide resolved

## Known Issues

It is important to note that unlike Rust's `String`, this `String` library does **not** guarantee a valid UTF-8 string. The `String` currently behaves only as a `vec` and does not perform any validation. This intended to be supported in the future with the introduction of [`char`](https://github.com/FuelLabs/sway/issues/2937) to the Sway language.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good comment, this clears up a lot of the confusion I was having with the lib


# Using the Library

## Getting Started

In order to use the `String` library it must be added to the Forc.toml file and then imported into your Sway project. To add Sway-libs as a dependency to the Forc.toml in your project, please see the [source README.md](../../../README.md).
bitzoic marked this conversation as resolved.
Show resolved Hide resolved

```rust
use sway_libs::string::String;
```

Once imported, a `String` can be instantiated defining a new variable and calling the `new` function.

```rust
let mut string = ~String::new();
```

## Basic Functionality

Appending or adding bytes to the `String` can be done by calling the `push` and `insert` functions.

```rust
string.push(0u8);
string.insert(0u8, 0);
bitzoic marked this conversation as resolved.
Show resolved Hide resolved
```

Removing bytes from the `String` can be done with either the `pop` or `remove` functions.

```rust
let last_byte = string.pop().unwrap();
let nth_byte = string.remove(0);
bitzoic marked this conversation as resolved.
Show resolved Hide resolved
```

To retrieve a byte in the `String`, use the `nth` function.

```rust
let nth_byte = string.nth(0);
bitzoic marked this conversation as resolved.
Show resolved Hide resolved
```

For more information please see the [specification](./SPECIFICATION.md).
63 changes: 63 additions & 0 deletions sway_libs/src/string/SPECIFICATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Overview
bitzoic marked this conversation as resolved.
Show resolved Hide resolved
matt-user marked this conversation as resolved.
Show resolved Hide resolved

This document provides an overview of the String library.

It outlines the use cases, i.e. specification, and describes how to implement the library.

## Use Cases

The String library can be used anytime a string's length is unknown at compile time and as such lives on the heap. Further methods can then be implemented to provide additional features building off of the `String` struct.
bitzoic marked this conversation as resolved.
Show resolved Hide resolved

> **Note** There is no guarantee in the validity of the UTF-8 encoded `String` and should be used with caution. For more information, please see the [known issues](./README.md#known-issues).

## Public Functions

### `as_bytes()`

Used to convert the `String` struct to a `Vec` of `u8` bytes.
bitzoic marked this conversation as resolved.
Show resolved Hide resolved

### `capacity()`

Returns the total amount of memory on the heap allocated to the `String` which can be filled with bytes.

> **Note** Capacity and length are not the same. A `String` may have a length of 0 but any arbitrary capacity.
bitzoic marked this conversation as resolved.
Show resolved Hide resolved

### `clear()`

Truncates the `String` to a length of 0 and will appear empty. This does not clear the capacity of the `String`.

### `from_utf8()`

Given a vector of `u8`'s a new `String` instance will be returned.
bitzoic marked this conversation as resolved.
Show resolved Hide resolved

### `insert()`

Inserts a new byte at the specified index in the `String`.

### `is_empty()`

Returns a boolean indicating whether the length of the `String` is zero.

### `len()`

Returns the total number of bytes in the `String`.

### `new()`

Creates a new instance of the `String` struct.

### `nth()`

Returns the byte at the specified index in the `String`. If the index is out of bounds, `None` is returned.

### `pop()`

Removes the last byte in the `String` and returns it. If the `String` does not have any bytes, `None` is returned.

### `remove()`

Will both remove and return the specified byte in the `String`.
bitzoic marked this conversation as resolved.
Show resolved Hide resolved

### `with_capacity()`

Creates a new instance of the `String` struct with a specified amount of memory allocated on the heap.
104 changes: 104 additions & 0 deletions sway_libs/src/string/string.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
library string;
Braqzen marked this conversation as resolved.
Show resolved Hide resolved

use std::{option::Option, vec::Vec};
Braqzen marked this conversation as resolved.
Show resolved Hide resolved

pub struct String {
bytes: Vec<u8>,
}

impl String {
/// Returns the bytes stored for the `String`.
pub fn as_bytes(self) -> Vec<u8> {
self.bytes
}

/// Gets the amount of memory on the heap allocated to the `String`.
pub fn capacity(self) -> u64 {
self.bytes.capacity()
}

/// Truncates this `String` to a length of zero, removing all contents.
pub fn clear(self) {
self.bytes.clear()
}

/// Converts a vector of bytes to a `String`.
///
/// # Arguments
///
/// * `bytes` - The vector of `u8` bytes which will be converted into a `String`.
pub fn from_utf8(bytes: Vec<u8>) -> String {
String { bytes }
}

/// Inserts a byte at the index within the `String`.
///
/// # Arguments
///
/// * `byte` - The element which will be added to the `String`.
/// * `index` - The position in the `String` where the byte will be inserted.
pub fn insert(self, byte: u8, index: u64) {
self.bytes.insert(index, byte);
}

/// Returns `true` if the vector contains no bytes.
pub fn is_empty(self) -> bool {
self.bytes.is_empty()
}

/// Returns the number of bytes in the `String`, also referred to
/// as its 'length'.
pub fn len(self) -> u64 {
self.bytes.len()
}

/// Constructs a new instance of the `String` type.
pub fn new() -> Self {
Self {
bytes: ~Vec::new(),
}
}

/// Returns the byte at the specified index.
///
/// # Arguments
///
/// * `index` - The position of the byte that will be returned.
pub fn nth(self, index: u64) -> Option<u8> {
self.bytes.get(index)
}

/// Removes the last byte from the `String` buffer and returns it.
pub fn pop(self) -> Option<u8> {
self.bytes.pop()
}

/// Appends a byte to the end of the `String`.
///
/// # Arguments
///
/// * `byte` - The element to be appended to the end of the `String`.
pub fn push(self, byte: u8) {
self.bytes.push(byte);
}

/// Removes and returns the byte at the specified index.
///
/// # Arguments
///
/// * `index` - The position of the byte that will be removed.
pub fn remove(self, index: u64) -> u8 {
self.bytes.remove(index)
}

/// Constructs a new instance of the `String` type with the specified capacity.
///
/// # Arguments
///
/// * `capacity` - The specified amount of memory on the heap to be allocated for the `String`.
pub fn with_capacity(capacity: u64) -> Self {
Self {
bytes: ~Vec::with_capacity(capacity),
}
}
}
1 change: 1 addition & 0 deletions tests/src/test_projects/harness.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Add test modules here:

mod merkle_proof;
mod string;
2 changes: 2 additions & 0 deletions tests/src/test_projects/string/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
out
target
8 changes: 8 additions & 0 deletions tests/src/test_projects/string/Forc.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[project]
authors = ["Fuel Labs <contact@fuel.sh>"]
entry = "main.sw"
license = "Apache-2.0"
name = "string"

[dependencies]
sway_libs = { path = "../../../../sway_libs" }
1 change: 1 addition & 0 deletions tests/src/test_projects/string/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mod tests;
Loading