odra_core/
gas_report.rs

1//! Module with structs for handling gas reports.
2use crate::prelude::*;
3use crate::CallDef;
4use casper_types::U512;
5use core::fmt::{Debug, Display, Formatter, Result};
6use serde::{Deserialize, Serialize};
7
8/// A Vector of deploy reports makes a full gas report.
9#[derive(Clone, Debug, Serialize, Deserialize, Default)]
10pub struct GasReport(Vec<DeployReport>);
11
12impl GasReport {
13    /// Adds a deploy report to the gas report.
14    pub fn push(&mut self, report: DeployReport) {
15        self.0.push(report)
16    }
17
18    /// Returns new, empty gas report.
19    pub fn new() -> Self {
20        GasReport::default()
21    }
22
23    /// Returns an iterator over the gas report.
24    pub fn iter(&self) -> Iter<'_, DeployReport> {
25        self.0.iter()
26    }
27}
28
29impl Display for GasReport {
30    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
31        for report in &self.0 {
32            writeln!(f, "{}", report)?;
33        }
34        Ok(())
35    }
36}
37
38impl IntoIterator for GasReport {
39    type Item = DeployReport;
40    type IntoIter = IntoIter<DeployReport>;
41
42    fn into_iter(self) -> Self::IntoIter {
43        self.0.into_iter()
44    }
45}
46
47/// Represents a deploy report, which includes the gas used and the deploy details.
48#[derive(Clone, Debug, Serialize, Deserialize)]
49pub enum DeployReport {
50    /// Represents a Wasm deploy.
51    WasmDeploy {
52        /// The gas used for the deploy.
53        gas: U512,
54        /// The file name of the deployed WASM.
55        file_name: String
56    },
57    /// Represents a contract call.
58    ContractCall {
59        /// The gas used for the call.
60        gas: U512,
61        /// The address of the contract called.
62        contract_address: Address,
63        /// The call definition.
64        call_def: CallDef
65    }
66}
67
68impl Display for DeployReport {
69    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
70        match self {
71            DeployReport::WasmDeploy { gas, file_name } => {
72                write!(
73                    f,
74                    "Wasm deploy: {} - {} CSPR",
75                    file_name,
76                    cspr_pretty_string(gas)
77                )
78            }
79            DeployReport::ContractCall { gas, call_def, .. } => {
80                write!(
81                    f,
82                    "Contract call: {} - {} CSPR",
83                    call_def.entry_point(),
84                    cspr_pretty_string(gas)
85                )
86            }
87        }
88    }
89}
90
91/// Render 1234567890 as 1.23456789
92fn cspr_pretty_string(cspr: &U512) -> String {
93    let cspr_top = cspr / U512::from(1_000_000_000);
94    let cspr_bottom = cspr % U512::from(1_000_000_000); // Use modulo to get the remainder
95    let cspr_bottom_str = format!("{:09}", cspr_bottom);
96    let mut cspr_bottom_str = cspr_bottom_str.trim_end_matches('0');
97    if cspr_bottom_str.is_empty() {
98        cspr_bottom_str = "0";
99    }
100    format!("{}.{}", cspr_top, cspr_bottom_str)
101}
102
103#[cfg(test)]
104mod tests {
105    use super::*;
106    use casper_types::account::AccountHash;
107    use casper_types::RuntimeArgs;
108
109    #[test]
110    fn test_deploy_report_display() {
111        let wasm_deploy = DeployReport::WasmDeploy {
112            gas: U512::from(1000),
113            file_name: String::from("test.wasm")
114        };
115        assert_eq!(
116            format!("{}", wasm_deploy),
117            "Wasm deploy: test.wasm - 0.000001 CSPR"
118        );
119
120        let contract_call = DeployReport::ContractCall {
121            gas: U512::from(1_000_000_000),
122            contract_address: Address::Account(AccountHash([0; 32])),
123            call_def: CallDef::new("test", false, RuntimeArgs::new())
124        };
125        assert_eq!(
126            format!("{}", contract_call),
127            "Contract call: test - 1.0 CSPR"
128        );
129    }
130}