Structs and enums

The structs and enums you define in your Sway code have equivalents automatically generated by the SDK's abigen! macro.

For instance, if in your Sway code you have a struct called CounterConfig that looks like this:

struct CounterConfig {
  dummy: bool,
  initial_value: u64,
}

After using the abigen! macro, CounterConfig will be accessible in your Rust file! Here's an example:

    abigen!(Contract(name="MyContract", abi="packages/fuels/tests/types/complex_types_contract/out/debug/complex_types_contract-abi.json"));

    // Here we can use `CounterConfig`, a struct originally
    // defined in the contract.
    let counter_config = CounterConfig {
        dummy: true,
        initial_value: 42,
    };

You can freely use your custom types (structs or enums) within this scope. That also means passing custom types to functions and receiving custom types from function calls.

Manual decoding

Suppose you wish to decode raw bytes into a type used in your contract and the abigen! generated this type, then you can use try_into:

    let shaker_in_bytes: Vec<u8> = vec![0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2];

    let expected = Shaker::Mojito(2);

    // as slice
    let actual: Shaker = shaker_in_bytes[..].try_into()?;
    assert_eq!(actual, expected);

    // as ref
    let actual: Shaker = (&shaker_in_bytes).try_into()?;
    assert_eq!(actual, expected);

    // as value
    let actual: Shaker = shaker_in_bytes.try_into()?;
    assert_eq!(actual, expected);

Otherwise, for native types such as u8, u32,...,ContractId and others, you must use ::fuels::core::try_from_bytes:

        let contract_id_bytes = [0xFF; 32];
        let contract_id = ContractId::new(contract_id_bytes);

        let asset_id_bytes = [0xFF; 32];
        let asset_id = AssetId::new(asset_id_bytes);

        let bytes: Vec<u8> = [contract_id_bytes, asset_id_bytes].concat();
        let expected: (ContractId, AssetId) = try_from_bytes(&bytes)?;

        assert_eq!(expected, (contract_id, asset_id));

Generics

The Fuel Rust SDK supports both generic enums and generic structs. If you're already familiar with Rust, it's your typical struct MyStruct<T> type of generics support.

For instance, your Sway contract could look like this:

contract;

use std::hash::sha256;

struct SimpleGeneric<T> {
    single_generic_param: T,
}

abi MyContract {
  fn struct_w_generic(arg1: SimpleGeneric<u64>) -> SimpleGeneric<u64>;
}

impl MyContract for Contract {
    fn struct_w_generic(arg1: SimpleGeneric<u64>) -> SimpleGeneric<u64> {
        let expected = SimpleGeneric {
            single_generic_param: 123u64,
        };

        assert(arg1.single_generic_param == expected.single_generic_param);

        expected
    }
}

Your Rust code would look like this:

        // simple struct with a single generic param
        let arg1 = SimpleGeneric {
            single_generic_param: 123u64,
        };

        let result = contract_methods
            .struct_w_generic(arg1.clone())
            .call()
            .await?
            .value;

        assert_eq!(result, arg1);