foundry_common_fmt/
dynamic.rsuse super::{format_int_exp, format_uint_exp};
use alloy_dyn_abi::{DynSolType, DynSolValue};
use alloy_primitives::hex;
use std::fmt;
struct DynValueFormatter {
raw: bool,
}
impl DynValueFormatter {
fn value(&self, value: &DynSolValue, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match value {
DynSolValue::Address(inner) => write!(f, "{inner}"),
DynSolValue::Function(inner) => write!(f, "{inner}"),
DynSolValue::Bytes(inner) => f.write_str(&hex::encode_prefixed(inner)),
DynSolValue::FixedBytes(word, size) => {
f.write_str(&hex::encode_prefixed(&word[..*size]))
}
DynSolValue::Uint(inner, _) => {
if self.raw {
write!(f, "{inner}")
} else {
f.write_str(&format_uint_exp(*inner))
}
}
DynSolValue::Int(inner, _) => {
if self.raw {
write!(f, "{inner}")
} else {
f.write_str(&format_int_exp(*inner))
}
}
DynSolValue::Array(values) | DynSolValue::FixedArray(values) => {
f.write_str("[")?;
self.list(values, f)?;
f.write_str("]")
}
DynSolValue::Tuple(values) => self.tuple(values, f),
DynSolValue::String(inner) => {
if self.raw {
write!(f, "{}", inner.escape_debug())
} else {
write!(f, "{inner:?}") }
}
DynSolValue::Bool(inner) => write!(f, "{inner}"),
DynSolValue::CustomStruct { name, prop_names, tuple } => {
if self.raw {
return self.tuple(tuple, f);
}
f.write_str(name)?;
if prop_names.len() == tuple.len() {
f.write_str("({ ")?;
for (i, (prop_name, value)) in std::iter::zip(prop_names, tuple).enumerate() {
if i > 0 {
f.write_str(", ")?;
}
f.write_str(prop_name)?;
f.write_str(": ")?;
self.value(value, f)?;
}
f.write_str(" })")
} else {
self.tuple(tuple, f)
}
}
}
}
fn list(&self, values: &[DynSolValue], f: &mut fmt::Formatter<'_>) -> fmt::Result {
for (i, value) in values.iter().enumerate() {
if i > 0 {
f.write_str(", ")?;
}
self.value(value, f)?;
}
Ok(())
}
fn tuple(&self, values: &[DynSolValue], f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("(")?;
self.list(values, f)?;
f.write_str(")")
}
}
struct DynValueDisplay<'a> {
value: &'a DynSolValue,
formatter: DynValueFormatter,
}
impl<'a> DynValueDisplay<'a> {
#[inline]
fn new(value: &'a DynSolValue, raw: bool) -> Self {
Self { value, formatter: DynValueFormatter { raw } }
}
}
impl fmt::Display for DynValueDisplay<'_> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.formatter.value(self.value, f)
}
}
pub fn parse_tokens<'a, I: IntoIterator<Item = (&'a DynSolType, &'a str)>>(
params: I,
) -> alloy_dyn_abi::Result<Vec<DynSolValue>> {
params.into_iter().map(|(param, value)| DynSolType::coerce_str(param, value)).collect()
}
pub fn format_tokens(tokens: &[DynSolValue]) -> impl Iterator<Item = String> + '_ {
tokens.iter().map(format_token)
}
pub fn format_tokens_raw(tokens: &[DynSolValue]) -> impl Iterator<Item = String> + '_ {
tokens.iter().map(format_token_raw)
}
pub fn format_token(value: &DynSolValue) -> String {
DynValueDisplay::new(value, false).to_string()
}
pub fn format_token_raw(value: &DynSolValue) -> String {
DynValueDisplay::new(value, true).to_string()
}
#[cfg(test)]
mod tests {
use super::*;
use alloy_primitives::{address, U256};
#[test]
fn parse_hex_uint() {
let ty = DynSolType::Uint(256);
let values = parse_tokens(std::iter::once((&ty, "100"))).unwrap();
assert_eq!(values, [DynSolValue::Uint(U256::from(100), 256)]);
let val: U256 = U256::from(100u64);
let hex_val = format!("0x{val:x}");
let values = parse_tokens(std::iter::once((&ty, hex_val.as_str()))).unwrap();
assert_eq!(values, [DynSolValue::Uint(U256::from(100), 256)]);
}
#[test]
fn format_addr() {
assert_eq!(
format_token(&DynSolValue::Address(address!(
"5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"
))),
"0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed",
);
assert_ne!(
format_token(&DynSolValue::Address(address!(
"Fb6916095cA1Df60bb79ce92cE3EA74c37c5d359"
))),
"0xFb6916095cA1Df60bb79ce92cE3EA74c37c5d359"
);
}
}