Skip to content

Commit

Permalink
feat: add from_hex_str for Bytes (#1205)
Browse files Browse the repository at this point in the history
Co-authored-by: Ahmed Sagdati <[email protected]>
  • Loading branch information
hal3e and segfault-magnet authored Nov 17, 2023
1 parent b9cac99 commit 5793398
Show file tree
Hide file tree
Showing 8 changed files with 102 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
- [Structs and enums](./types/custom_types.md)
- [String](./types/string.md)
- [Bits256](./types/bits256.md)
- [Bytes](./types/bytes.md)
- [B512](./types/B512.md)
- [EvmAddress](./types/evm_address.md)
- [Vectors](./types/vectors.md)
Expand Down
13 changes: 13 additions & 0 deletions docs/src/types/bytes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Bytes

In Fuel, a type called `Bytes` represents a collection of tightly-packed bytes. The Rust SDK represents `Bytes` as `Bytes(Vec<u8>)`. Here's an example of using `Bytes` in a contract call:

```rust,ignore
{{#include ../../../packages/fuels/tests/types_contracts.rs:bytes_arg}}
```

If you have a hexadecimal value as a string and wish to convert it to `Bytes`, you may do so with `from_hex_str`:

```rust,ignore
{{#include ../../../packages/fuels-core/src/types/core/bytes.rs:bytes_from_hex_str}}
```
48 changes: 48 additions & 0 deletions packages/fuels-core/src/types/core/bytes.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,29 @@
use crate::types::errors::{error, Result};

#[derive(Debug, PartialEq, Clone, Eq)]
pub struct Bytes(pub Vec<u8>);

impl Bytes {
/// Create a new `Bytes` from a string representation of a hex.
/// Accepts both `0x` prefixed and non-prefixed hex strings.
pub fn from_hex_str(hex: &str) -> Result<Self> {
let hex = if let Some(stripped_hex) = hex.strip_prefix("0x") {
stripped_hex
} else {
hex
};

let bytes = hex::decode(hex).map_err(|e| {
error!(
InvalidData,
"Could not convert hex str '{hex}' to Bytes! {e}"
)
})?;

Ok(Bytes(bytes))
}
}

impl From<Bytes> for Vec<u8> {
fn from(raw_slice: Bytes) -> Vec<u8> {
raw_slice.0
Expand All @@ -18,3 +41,28 @@ impl PartialEq<Bytes> for Vec<u8> {
*self == other.0
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn from_hex_str_b256() -> Result<()> {
// ANCHOR: bytes_from_hex_str
let hex_str = "0101010101010101010101010101010101010101010101010101010101010101";

let bytes = Bytes::from_hex_str(hex_str)?;

assert_eq!(bytes.0, vec![1u8; 32]);

// With the `0x0` prefix
let hex_str = "0x0101010101010101010101010101010101010101010101010101010101010101";

let bytes = Bytes::from_hex_str(hex_str)?;

assert_eq!(bytes.0, vec![1u8; 32]);
// ANCHOR_END: bytes_from_hex_str

Ok(())
}
}
1 change: 1 addition & 0 deletions packages/fuels/Forc.toml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ members = [
'tests/types/predicates/address',
'tests/types/predicates/enums',
'tests/types/predicates/predicate_bytes',
'tests/types/predicates/predicate_bytes_hash',
'tests/types/predicates/predicate_generics',
'tests/types/predicates/predicate_raw_slice',
'tests/types/predicates/predicate_std_lib_string',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[project]
authors = ["Fuel Labs <[email protected]>"]
entry = "main.sw"
license = "Apache-2.0"
name = "predicate_bytes_hash"
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
predicate;

use std::bytes::Bytes;
use std::hash::{Hash, sha256};

fn main(bytes: Bytes, hash: b256) -> bool {
sha256(bytes) == hash
}
2 changes: 2 additions & 0 deletions packages/fuels/tests/types_contracts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1938,9 +1938,11 @@ async fn test_bytes_as_input() -> Result<()> {
let contract_methods = contract_instance.methods();

{
// ANCHOR: bytes_arg
let bytes = Bytes(vec![40, 41, 42]);

contract_methods.accept_bytes(bytes).call().await?;
// ANCHOR_END: bytes_arg
}
{
let bytes = Bytes(vec![40, 41, 42]);
Expand Down
24 changes: 24 additions & 0 deletions packages/fuels/tests/types_predicates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use fuels::{
prelude::*,
types::{coin::Coin, message::Message, unresolved_bytes::UnresolvedBytes, AssetId, U256},
};
use fuels_core::types::Bits256;

async fn assert_predicate_spendable(
data: UnresolvedBytes,
Expand Down Expand Up @@ -278,6 +279,29 @@ async fn spend_predicate_coins_messages_generics() -> Result<()> {
Ok(())
}

#[tokio::test]
async fn spend_predicate_coins_messages_bytes_hash() -> Result<()> {
abigen!(Predicate(
name = "MyPredicate",
abi = "packages/fuels/tests/types/predicates/predicate_bytes_hash/out/debug/predicate_bytes_hash-abi.json"

));

let bytes = Bytes::from_hex_str(
"0x75a448b91bb82a255757e61ba3eb7afe282c09842485268d4d72a027ec0cffc80500000000",
)?;

let bits256 = Bits256::from_hex_str(
"0x173d69ea3d0aa050d01ff7cc60ccd4579b567c465cd115c6876c2da4a332fb99",
)?;

let data = MyPredicateEncoder::encode_data(bytes, bits256);

assert_predicate_spendable(data, "tests/types/predicates/predicate_bytes_hash").await?;

Ok(())
}

#[tokio::test]
async fn spend_predicate_coins_messages_bytes() -> Result<()> {
abigen!(Predicate(
Expand Down

0 comments on commit 5793398

Please sign in to comment.