Skip to content

Commit

Permalink
Refactor Bytes type to use From trait (FuelLabs#4714)
Browse files Browse the repository at this point in the history
## Description

The current use of converting `Bytes` to and from `raw_slice` and `Vec`
use a special define function. This should use the `From` trait.

> Note: This is a breaking change.

## 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 Jun 29, 2023
1 parent 1544bb0 commit 8aabcd3
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 89 deletions.
220 changes: 135 additions & 85 deletions sway-lib-std/src/bytes.sw
Original file line number Diff line number Diff line change
Expand Up @@ -485,75 +485,6 @@ impl Bytes {

// Need to use seperate impl blocks for now: https://github.com/FuelLabs/sway/issues/1548
impl Bytes {
/// Creates a `Bytes` from a `Vec<u8>`.
///
/// ### Examples
///
/// ```sway
/// use std:bytes::Bytes;
///
/// let mut vec = Vec::new();
/// let a = 5u8;
/// let b = 7u8;
/// let c = 9u8
///
/// vec.push(a);
/// vec.push(b);
/// vec.push(c);
///
/// let bytes = Bytes::from_vec_u8(vec);
///
/// assert(bytes.len == 3);
/// assert(bytes.get(0).unwrap() == a);
/// assert(bytes.get(1).unwrap() == b);
/// assert(bytes.get(2).unwrap() == c);
/// ```
pub fn from_vec_u8(ref mut vec: Vec<u8>) -> Self {
let mut bytes = Bytes::new();
let mut i = 0;
let length = vec.len();
while i < length {
bytes.push(vec.get(i).unwrap());
i += 1;
};
bytes
}

/// Creates a `Vec<u8>` from a `Bytes`.
///
/// ### Examples
///
/// ```sway
/// use std:bytes::Bytes;
///
/// let mut bytes = Bytes::new();
/// let a = 5u8;
/// let b = 7u8;
/// let c = 9u8
/// bytes.push(a);
/// bytes.push(b);
/// bytes.push(c);
///
/// assert(bytes.len() == 3);
///
/// let vec = bytes.into_vec_u8();
///
/// assert(vec.len() == 3);
/// assert(vec.get(0).unwrap() == a);
/// assert(vec.get(1).unwrap() == b);
/// assert(vec.get(2).unwrap() == c);
/// ```
pub fn into_vec_u8(self) -> Vec<u8> {
let mut vec = Vec::new();
let mut i = 0;
let length = self.len;
while i < length {
vec.push(self.get(i).unwrap());
i += 1;
};
vec
}

/// Divides one Bytes into two at an index.
///
/// The first will contain all indices from `[0, mid)` (excluding the index
Expand Down Expand Up @@ -669,18 +600,6 @@ impl Bytes {
// clear `other`
other.clear();
}

// Should be remove and replace when https://github.com/FuelLabs/sway/pull/3882 is resovled
pub fn from_raw_slice(slice: raw_slice) -> Self {
let number_of_bytes = slice.number_of_bytes();
Self {
buf: RawBytes {
ptr: slice.ptr(),
cap: number_of_bytes,
},
len: number_of_bytes,
}
}
}

impl core::ops::Eq for Bytes {
Expand Down Expand Up @@ -728,6 +647,137 @@ impl From<b256> for Bytes {
}
}

impl From<raw_slice> for Bytes {
/// Creates a `Bytes` from a `raw_slice`.
///
/// ### Examples
///
/// ```sway
/// use std:bytes::Bytes;
///
/// let mut vec = Vec::new();
/// let a = 5u8;
/// let b = 7u8;
/// let c = 9u8
///
/// vec.push(a);
/// vec.push(b);
/// vec.push(c);
///
/// let vec_as_raw_slice = vec.as_raw_slice();
/// let bytes = Bytes::from(vec_as_raw_slice);
///
/// assert(bytes.len == 3);
/// assert(bytes.get(0).unwrap() == a);
/// assert(bytes.get(1).unwrap() == b);
/// assert(bytes.get(2).unwrap() == c);
/// ```
fn from(slice: raw_slice) -> Self {
let number_of_bytes = slice.number_of_bytes();
Self {
buf: RawBytes {
ptr: slice.ptr(),
cap: number_of_bytes,
},
len: number_of_bytes,
}
}

/// Creates a `raw_slice` from a `Bytes`.
///
/// ### Examples
///
/// ```sway
/// use std:bytes::Bytes;
///
/// let mut bytes = Bytes::new();
/// let a = 5u8;
/// let b = 7u8;
/// let c = 9u8
/// bytes.push(a);
/// bytes.push(b);
/// bytes.push(c);
///
/// assert(bytes.len() == 3);
///
/// let slice: raw_slice = bytes.into();
///
/// assert(slice.number_of_bytes() == 3);
/// ```
fn into(self) -> raw_slice {
asm(ptr: (self.buf.ptr(), self.len)) { ptr: raw_slice }
}
}

impl From<Vec<u8>> for Bytes {
/// Creates a `Bytes` from a `Vec<u8>`.
///
/// ### Examples
///
/// ```sway
/// use std:bytes::Bytes;
///
/// let mut vec = Vec::new();
/// let a = 5u8;
/// let b = 7u8;
/// let c = 9u8
///
/// vec.push(a);
/// vec.push(b);
/// vec.push(c);
///
/// let bytes = Bytes::from(vec);
///
/// assert(bytes.len == 3);
/// assert(bytes.get(0).unwrap() == a);
/// assert(bytes.get(1).unwrap() == b);
/// assert(bytes.get(2).unwrap() == c);
/// ```
fn from(vec: Vec<u8>) -> Self {
let mut bytes = Bytes::with_capacity(vec.len());
let mut i = 0;
while i < vec.len() {
bytes.push(vec.get(i).unwrap());
i += 1;
};
bytes
}

/// Creates a `Vec<u8>` from a `Bytes`.
///
/// ### Examples
///
/// ```sway
/// use std:bytes::Bytes;
///
/// let mut bytes = Bytes::new();
/// let a = 5u8;
/// let b = 7u8;
/// let c = 9u8
/// bytes.push(a);
/// bytes.push(b);
/// bytes.push(c);
///
/// assert(bytes.len() == 3);
///
/// let vec: Vec<u8> = bytes.into();
///
/// assert(vec.len() == 3);
/// assert(vec.get(0).unwrap() == a);
/// assert(vec.get(1).unwrap() == b);
/// assert(vec.get(2).unwrap() == c);
/// ```
fn into(self) -> Vec<u8> {
let mut vec = Vec::with_capacity(self.len);
let mut i = 0;
while i < self.len {
vec.push(self.get(i).unwrap());
i += 1;
};
vec
}
}

// Tests
//
fn setup() -> (Bytes, u8, u8, u8) {
Expand Down Expand Up @@ -925,7 +975,7 @@ fn test_from_vec_u8() {
vec.push(b);
vec.push(c);

let bytes = Bytes::from_vec_u8(vec);
let bytes = Bytes::from(vec);

assert(bytes.len == 3);
assert(bytes.get(0).unwrap() == a);
Expand All @@ -938,7 +988,7 @@ fn test_into_vec_u8() {
let (mut bytes, a, b, c) = setup();
assert(bytes.len() == 3);

let vec = bytes.into_vec_u8();
let vec: Vec<u8> = bytes.into();

assert(vec.len() == 3);
assert(vec.get(0).unwrap() == a);
Expand Down Expand Up @@ -1140,7 +1190,7 @@ fn test_keccak256() {
fn test_as_raw_slice() {
let val = 0x3497297632836282349729763283628234972976328362823497297632836282;
let slice_1 = asm(ptr: (__addr_of(val), 32)) { ptr: raw_slice };
let mut bytes = Bytes::from_raw_slice(slice_1);
let mut bytes = Bytes::from(slice_1);
let slice_2 = bytes.as_raw_slice();
assert(slice_1.ptr() == slice_2.ptr());
assert(slice_1.number_of_bytes() == slice_2.number_of_bytes());
Expand All @@ -1151,7 +1201,7 @@ fn test_as_raw_slice() {
fn test_from_raw_slice() {
let val = 0x3497297632836282349729763283628234972976328362823497297632836282;
let slice_1 = asm(ptr: (__addr_of(val), 32)) { ptr: raw_slice };
let mut bytes = Bytes::from_raw_slice(slice_1);
let mut bytes = Bytes::from(slice_1);
let slice_2 = bytes.as_raw_slice();
assert(slice_1.ptr() == slice_2.ptr());
assert(slice_1.number_of_bytes() == slice_2.number_of_bytes());
Expand Down
2 changes: 1 addition & 1 deletion sway-lib-std/src/low_level_call.sw
Original file line number Diff line number Diff line change
Expand Up @@ -107,5 +107,5 @@ pub fn call_with_function_selector_vec(
let mut function_selector = function_selector;
let mut calldata = calldata;

call_with_function_selector(target, Bytes::from_vec_u8(function_selector), Bytes::from_vec_u8(calldata), single_value_type_arg, call_params);
call_with_function_selector(target, Bytes::from(function_selector), Bytes::from(calldata), single_value_type_arg, call_params);
}
2 changes: 1 addition & 1 deletion sway-lib-std/src/storage/storage_bytes.sw
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ impl StorableSlice<Bytes> for StorageKey<StorageBytes> {
fn read_slice(self) -> Option<Bytes> {
match read_slice(self.field_id) {
Some(slice) => {
Some(Bytes::from_raw_slice(slice))
Some(Bytes::from(slice))
},
None => None,
}
Expand Down
4 changes: 2 additions & 2 deletions test/src/sdk-harness/test_projects/storage_bytes/src/main.sw
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ impl StorageBytesTest for Contract {
#[storage(read, write)]
fn store_bytes(vec: Vec<u8>) {
let mut vec = vec;
let bytes = Bytes::from_vec_u8(vec);
let bytes = Bytes::from(vec);

storage.bytes.write_slice(bytes);
}

#[storage(read)]
fn assert_stored_bytes(vec: Vec<u8>) {
let mut vec = vec;
let bytes = Bytes::from_vec_u8(vec);
let bytes = Bytes::from(vec);
let stored_bytes = storage.bytes.read_slice().unwrap();

assert(bytes.len() == stored_bytes.len());
Expand Down

0 comments on commit 8aabcd3

Please sign in to comment.