fuels-macros 0.77.0

Fuel Rust SDK macros to generate types from ABI.
Documentation
use std::collections::HashSet;

use fuels_code_gen::ProgramType;
use proc_macro2::Span;
use syn::{Error, LitStr, Result};

use crate::{
    parse_utils::ErrorsExt,
    setup_program_test::parsing::{
        AbigenCommand, DeployContractCommand, InitializeWalletCommand, LoadScriptCommand,
    },
};

pub(crate) fn extract_the_abigen_command(
    parent_span: Span,
    abigen_commands: &[AbigenCommand],
) -> Result<AbigenCommand> {
    match abigen_commands {
        [single_command] => Ok(single_command.clone()),
        commands => {
            let err = commands
                .iter()
                .map(|command| Error::new(command.span, "Only one `Abigen` command allowed"))
                .combine_errors()
                .unwrap_or_else(|| Error::new(parent_span, "Add an `Abigen(..)` command!"));

            Err(err)
        }
    }
}

pub(crate) fn validate_all_contracts_are_known(
    abigen_command: &AbigenCommand,
    deploy_commands: &[DeployContractCommand],
) -> Result<()> {
    extract_contracts_to_deploy(deploy_commands)
        .difference(&names_of_program_bindings(
            abigen_command,
            ProgramType::Contract,
        ))
        .flat_map(|unknown_contract| {
            [
                Error::new_spanned(unknown_contract, "Contract is unknown"),
                Error::new(
                    abigen_command.span,
                    format!(
                        "Consider adding: Contract(name=\"{}\", project=...)",
                        unknown_contract.value()
                    ),
                ),
            ]
        })
        .validate_no_errors()
}

pub(crate) fn validate_all_scripts_are_known(
    abigen_command: &AbigenCommand,
    load_commands: &[LoadScriptCommand],
) -> Result<()> {
    extract_scripts_to_load(load_commands)
        .difference(&names_of_program_bindings(
            abigen_command,
            ProgramType::Script,
        ))
        .flat_map(|unknown_contract| {
            [
                Error::new_spanned(unknown_contract, "Script is unknown"),
                Error::new(
                    abigen_command.span,
                    format!(
                        "Consider adding: Script(name=\"{}\", project=...)",
                        unknown_contract.value()
                    ),
                ),
            ]
        })
        .validate_no_errors()
}

pub(crate) fn validate_zero_or_one_wallet_command_present(
    commands: &[InitializeWalletCommand],
) -> Result<()> {
    if commands.len() > 1 {
        commands
            .iter()
            .map(|command| Error::new(command.span, "Only one `Wallets` command allowed"))
            .combine_errors()
            .map(Err)
            .expect("Known to have at least one error")
    } else {
        Ok(())
    }
}

fn names_of_program_bindings(
    commands: &AbigenCommand,
    program_type: ProgramType,
) -> HashSet<&LitStr> {
    commands
        .targets
        .iter()
        .filter_map(|target| (target.program_type == program_type).then_some(&target.name))
        .collect()
}

fn extract_contracts_to_deploy(commands: &[DeployContractCommand]) -> HashSet<&LitStr> {
    commands.iter().map(|c| &c.contract).collect()
}

fn extract_scripts_to_load(commands: &[LoadScriptCommand]) -> HashSet<&LitStr> {
    commands.iter().map(|c| &c.script).collect()
}