diff --git a/Cargo.lock b/Cargo.lock index d052250..014a784 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2405,6 +2405,7 @@ dependencies = [ "futures", "futures-util", "glob", + "indexmap", "itertools 0.13.0", "rpassword", "rustyline 14.0.0", diff --git a/Cargo.toml b/Cargo.toml index 60b5321..1b1fe2b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,3 +29,4 @@ async-trait = "0.1.80" futures-util = "0.3.30" semver = "1.0.23" shellexpand = { version = "3.1.0", features = ["path"] } +indexmap = "2.2.6" diff --git a/src/interpreter/interpreter.rs b/src/interpreter/interpreter.rs index 67beec6..60430ec 100644 --- a/src/interpreter/interpreter.rs +++ b/src/interpreter/interpreter.rs @@ -1,5 +1,4 @@ use std::cmp::Ordering; -use std::collections::BTreeMap; use std::ops::{Add, Div, Mul, Neg, Rem, Sub}; use std::str::FromStr; @@ -7,6 +6,7 @@ use alloy::hex::FromHex; use alloy::primitives::{Address, B256, I256, U256}; use anyhow::{anyhow, bail, Result}; use futures::future::{BoxFuture, FutureExt}; +use indexmap::IndexMap; use solang_parser::pt::{ContractPart, Expression, Statement}; use crate::loaders::types::Project; @@ -519,7 +519,7 @@ pub fn evaluate_expression(env: &mut Env, expr: Box) -> BoxFuture<'_ } else { bail!("expected variable, found {:?}", name_expr); }; - let mut fields = BTreeMap::new(); + let mut fields = IndexMap::new(); for arg in args.iter() { let value = evaluate_expression(env, Box::new(arg.expr.clone())).await?; fields.insert(arg.name.name.clone(), value); diff --git a/src/interpreter/types.rs b/src/interpreter/types.rs index e2267fc..b40f29d 100644 --- a/src/interpreter/types.rs +++ b/src/interpreter/types.rs @@ -1,4 +1,4 @@ -use std::{collections::BTreeMap, fmt::Display}; +use std::fmt::Display; use alloy::{ dyn_abi::DynSolType, @@ -7,6 +7,7 @@ use alloy::{ rpc::types::{Log, TransactionReceipt}, }; use anyhow::{bail, Result}; +use indexmap::IndexMap; use itertools::Itertools; use super::{ @@ -110,7 +111,7 @@ pub enum Type { String, Array(Box), FixedArray(Box, usize), - NamedTuple(String, BTreeMap), + NamedTuple(String, IndexMap), Tuple(Vec), Contract(ContractInfo), Transaction, @@ -311,7 +312,7 @@ impl Type { Ok(Value::FixBytes(B256::from_slice(&new_vector), *size)) } (Type::NamedTuple(name, types_), Value::Tuple(values)) => { - let mut new_values = BTreeMap::new(); + let mut new_values = IndexMap::new(); for (key, value) in types_.iter().zip(values.iter()) { new_values.insert(key.0.clone(), key.1.cast(value)?); } diff --git a/src/interpreter/value.rs b/src/interpreter/value.rs index fd6336a..0ce0ba8 100644 --- a/src/interpreter/value.rs +++ b/src/interpreter/value.rs @@ -4,9 +4,9 @@ use alloy::{ primitives::{Address, B256, I256, U256}, }; use anyhow::{bail, Result}; +use indexmap::IndexMap; use itertools::Itertools; use std::{ - collections::BTreeMap, fmt::{self, Display, Formatter}, ops::{Add, Div, Mul, Rem, Sub}, }; @@ -28,7 +28,7 @@ pub enum Value { Addr(Address), Contract(ContractInfo, Address), Tuple(Vec), - NamedTuple(String, BTreeMap), + NamedTuple(String, IndexMap), Array(Vec), TypeObject(Type), Transaction(B256), @@ -40,7 +40,7 @@ fn _values_to_string(values: &[Value]) -> String { values.iter().map(|v| format!("{}", v)).join(", ") } -fn _format_struct_fields(fields: &BTreeMap) -> String { +fn _format_struct_fields(fields: &IndexMap) -> String { fields .iter() .map(|(k, v)| format!("{}: {}", k, v)) @@ -125,7 +125,7 @@ impl TryFrom<&Value> for alloy::dyn_abi::DynSolValue { impl From for Value { fn from(log: alloy::rpc::types::Log) -> Self { - let mut fields = BTreeMap::new(); + let mut fields = IndexMap::new(); fields.insert("address".to_string(), Value::Addr(log.address())); fields.insert( "topics".to_string(), @@ -166,7 +166,7 @@ impl TryFrom for Value { .zip(tuple) .map(|(k, dv)| Value::try_from(dv).map(|v| (k.clone(), v))) .collect::>>()?; - Ok(Value::NamedTuple(name, BTreeMap::from_iter(vs))) + Ok(Value::NamedTuple(name, IndexMap::from_iter(vs))) } v => Err(anyhow::anyhow!("{:?} not supported", v)), }