aeri 0.2.4

Aeri is a Cardano smart contract language by Knott Dynamics, created by Trevor Knott, with its official compiler and CLI.
Documentation
use serde::Serialize;

use crate::{Result, compile_source};

#[derive(Debug, Clone, Serialize, PartialEq, Eq)]
/// Aggregate budget estimate for one compilation unit.
pub struct CostReport {
    /// Per-validator cost estimates.
    pub validators: Vec<ValidatorCost>,
    /// Total serialized byte size across all validators.
    pub total_bytes: usize,
    /// Total node count across all validators.
    pub total_nodes: usize,
    /// Sum of estimated budget units across all validators.
    pub total_budget_units: usize,
}

#[derive(Debug, Clone, Serialize, PartialEq, Eq)]
/// Cost estimate details for a single validator.
pub struct ValidatorCost {
    /// Validator title used in output artifacts.
    pub title: String,
    /// Script purpose inferred from parameters (`spending`, `minting`, ...).
    pub script_purpose: String,
    /// Estimated source size proxy in bytes.
    pub bytes: usize,
    /// Estimated node count proxy in IR.
    pub nodes: usize,
    /// Estimated budget units (`bytes * 2 + nodes * 100`).
    pub budget_units: usize,
}

/// Estimate compile size/budget for all validators in a source module.
pub fn estimate_source(file: &str, source: &str) -> Result<CostReport> {
    let output = compile_source(file, source)?;
    let validators = output
        .blueprint
        .validators
        .iter()
        .map(|validator| {
            let bytes = validator.compiled_code.len();
            let nodes = validator.compiled_code.matches('(').count();
            ValidatorCost {
                title: validator.title.clone(),
                script_purpose: validator.script_purpose.clone(),
                bytes,
                nodes,
                budget_units: budget_units(bytes, nodes),
            }
        })
        .collect::<Vec<_>>();

    Ok(report(validators))
}

/// Build an aggregate cost report from individual validator estimates.
pub fn report(validators: Vec<ValidatorCost>) -> CostReport {
    CostReport {
        total_bytes: validators.iter().map(|cost| cost.bytes).sum(),
        total_nodes: validators.iter().map(|cost| cost.nodes).sum(),
        total_budget_units: validators.iter().map(|cost| cost.budget_units).sum(),
        validators,
    }
}

/// Current rough budget unit estimator used by the CLI and docs output.
pub fn budget_units(bytes: usize, nodes: usize) -> usize {
    bytes.saturating_mul(2) + nodes.saturating_mul(100)
}