use std::sync::Arc;
use crate::storage::codec::SolArrayBuilder;
use alloy::{
dyn_abi::{DynSolEvent, DynSolType, DynSolValue, Specifier},
hex::ToHexExt,
json_abi::Event,
rpc::types::Log,
};
use alloy_primitives::U256;
use anyhow::Result;
use arrow::{
array::{self, Array, ArrayBuilder, ArrayRef, RecordBatch},
datatypes::SchemaRef,
};
pub struct BatchEventEncoder {
dyn_event: DynSolEvent,
schema: SchemaRef,
header: Vec<Box<dyn SolArrayBuilder + Send>>, indexed: Vec<Box<dyn SolArrayBuilder + Send>>, data: Vec<Box<dyn SolArrayBuilder + Send>>, }
impl BatchEventEncoder {
pub fn new(event: &Event, schema: SchemaRef) -> Result<Self> {
let dyn_event = event.resolve().unwrap();
let header: Vec<Box<dyn SolArrayBuilder + Send>> = vec![
Box::<SolArrayBuilderUInt64>::default(), Box::<SolArrayBuilderUInt32>::default(), Box::<SolArrayBuilderString>::default(), ];
let indexed: Vec<Box<dyn SolArrayBuilder + Send>> = event
.inputs
.iter()
.filter(|p| p.indexed)
.map(|param| dyn_sol_type_to_array_builder(¶m.ty.resolve().unwrap()))
.collect();
let data: Vec<Box<dyn SolArrayBuilder + Send>> = event
.inputs
.iter()
.filter(|p| !p.indexed)
.map(|param| dyn_sol_type_to_array_builder(¶m.ty.resolve().unwrap()))
.collect();
Ok(BatchEventEncoder {
dyn_event,
schema,
header,
indexed,
data,
})
}
pub fn append(&mut self, log: &Log) {
let decoded = self.dyn_event.decode_log_data(log.data());
match decoded {
Ok(event_data) => {
self.header[0].append_value(&DynSolValue::Uint(
U256::from(log.block_number.unwrap()),
64,
)); self.header[1]
.append_value(&DynSolValue::Uint(U256::from(log.log_index.unwrap()), 32)); self.header[2].append_value(&DynSolValue::Address(log.address()));
for (val, builder) in event_data.indexed.iter().zip(self.indexed.iter_mut()) {
builder.append_value(val);
}
for (val, builder) in event_data.body.iter().zip(self.data.iter_mut()) {
builder.append_value(val);
}
}
Err(e) => {
tracing::warn!("Failed to decode log: {:?}", e);
}
}
}
pub fn finish(&mut self) -> Result<RecordBatch> {
let columns: Vec<ArrayRef> = self
.header
.iter_mut()
.map(|b| b.finish())
.chain(self.indexed.iter_mut().map(|b| b.finish()))
.chain(self.data.iter_mut().map(|b| b.finish()))
.collect();
let result = RecordBatch::try_new(self.schema.clone(), columns)?;
Ok(result)
}
pub fn append_iter<'a, I>(&mut self, logs: I) -> Result<()>
where
I: IntoIterator<Item = &'a Log>,
{
for log in logs {
self.append(log);
}
Ok(())
}
pub fn len(&self) -> usize {
self.header[0].len()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
fn dyn_sol_type_to_array_builder(ty: &DynSolType) -> Box<dyn SolArrayBuilder + Send> {
match ty {
DynSolType::Bool => Box::new(SolArrayBuilderBool::default()),
DynSolType::Int(n) => {
if *n > 64 {
Box::new(SolArrayBuilderString::default())
} else if *n > 32 {
Box::new(SolArrayBuilderInt64::default())
} else if *n > 16 {
Box::new(SolArrayBuilderInt32::default())
} else if *n > 8 {
Box::new(SolArrayBuilderInt16::default())
} else {
Box::new(SolArrayBuilderInt8::default())
}
}
DynSolType::Uint(n) => {
if *n > 64 {
Box::new(SolArrayBuilderString::default())
} else if *n > 32 {
Box::new(SolArrayBuilderUInt64::default())
} else if *n > 16 {
Box::new(SolArrayBuilderUInt32::default())
} else if *n > 8 {
Box::new(SolArrayBuilderUInt16::default())
} else {
Box::new(SolArrayBuilderUInt8::default())
}
}
DynSolType::Address | DynSolType::String => Box::new(SolArrayBuilderString::default()),
DynSolType::Bytes | DynSolType::FixedBytes(_) => Box::new(SolArrayBuilderBytes::default()),
_ => unimplemented!(
"Support for transcoding {ty} solidity type to arrow is not yet implemented",
),
}
}
#[derive(Default)]
pub struct SolArrayBuilderBool {
builder: array::BooleanBuilder,
}
impl SolArrayBuilder for SolArrayBuilderBool {
fn append_value(&mut self, value: &DynSolValue) {
match value {
DynSolValue::Bool(v) => self.builder.append_value(*v),
_ => panic!("Unexpected value {value:?}"),
}
}
fn len(&self) -> usize {
self.builder.len()
}
fn finish(&mut self) -> Arc<dyn Array> {
Arc::new(self.builder.finish())
}
}
#[derive(Default)]
struct SolArrayBuilderInt64 {
builder: array::Int64Builder,
}
impl SolArrayBuilder for SolArrayBuilderInt64 {
fn append_value(&mut self, value: &DynSolValue) {
match value {
DynSolValue::Int(v, _) => {
self.builder.append_value(v.low_i64());
}
_ => panic!("Unexpected value {value:?}"),
}
}
fn len(&self) -> usize {
self.builder.len()
}
fn finish(&mut self) -> Arc<dyn Array> {
Arc::new(self.builder.finish())
}
}
#[derive(Default)]
struct SolArrayBuilderInt32 {
builder: array::Int32Builder,
}
impl SolArrayBuilder for SolArrayBuilderInt32 {
fn append_value(&mut self, value: &DynSolValue) {
match value {
DynSolValue::Int(v, _) => self.builder.append_value(v.low_i32()),
_ => panic!("Unexpected value {value:?}"),
}
}
fn len(&self) -> usize {
self.builder.len()
}
fn finish(&mut self) -> Arc<dyn Array> {
Arc::new(self.builder.finish())
}
}
#[derive(Default)]
struct SolArrayBuilderInt16 {
builder: array::Int16Builder,
}
impl SolArrayBuilder for SolArrayBuilderInt16 {
fn append_value(&mut self, value: &DynSolValue) {
match value {
DynSolValue::Int(v, _) => self.builder.append_value(v.low_i16()),
_ => panic!("Unexpected value {value:?}"),
}
}
fn len(&self) -> usize {
self.builder.len()
}
fn finish(&mut self) -> Arc<dyn Array> {
Arc::new(self.builder.finish())
}
}
#[derive(Default)]
struct SolArrayBuilderInt8 {
builder: array::Int8Builder,
}
impl SolArrayBuilder for SolArrayBuilderInt8 {
fn append_value(&mut self, value: &DynSolValue) {
match value {
DynSolValue::Int(v, _) => self.builder.append_value(v.low_i8()),
_ => panic!("Unexpected value {value:?}"),
}
}
fn len(&self) -> usize {
self.builder.len()
}
fn finish(&mut self) -> Arc<dyn Array> {
Arc::new(self.builder.finish())
}
}
#[derive(Default)]
struct SolArrayBuilderUInt64 {
builder: array::UInt64Builder,
}
impl SolArrayBuilder for SolArrayBuilderUInt64 {
fn append_value(&mut self, value: &DynSolValue) {
match value {
DynSolValue::Uint(v, _) => self.builder.append_value(v.as_limbs()[0]),
_ => panic!("Unexpected value {value:?}"),
}
}
fn len(&self) -> usize {
self.builder.len()
}
fn finish(&mut self) -> Arc<dyn Array> {
Arc::new(self.builder.finish())
}
}
#[derive(Default)]
struct SolArrayBuilderUInt32 {
builder: array::UInt32Builder,
}
impl SolArrayBuilder for SolArrayBuilderUInt32 {
fn append_value(&mut self, value: &DynSolValue) {
match value {
DynSolValue::Uint(v, _) => self.builder.append_value(v.as_limbs()[0] as u32),
_ => panic!("Unexpected value {value:?}"),
}
}
fn len(&self) -> usize {
self.builder.len()
}
fn finish(&mut self) -> Arc<dyn Array> {
Arc::new(self.builder.finish())
}
}
#[derive(Default)]
struct SolArrayBuilderUInt16 {
builder: array::UInt16Builder,
}
impl SolArrayBuilder for SolArrayBuilderUInt16 {
fn append_value(&mut self, value: &DynSolValue) {
match value {
DynSolValue::Uint(v, _) => self.builder.append_value(v.as_limbs()[0] as u16),
_ => panic!("Unexpected value {value:?}"),
}
}
fn len(&self) -> usize {
self.builder.len()
}
fn finish(&mut self) -> Arc<dyn Array> {
Arc::new(self.builder.finish())
}
}
#[derive(Default)]
struct SolArrayBuilderUInt8 {
builder: array::UInt8Builder,
}
impl SolArrayBuilder for SolArrayBuilderUInt8 {
fn append_value(&mut self, value: &DynSolValue) {
match value {
DynSolValue::Uint(v, _) => self.builder.append_value(v.as_limbs()[0] as u8),
_ => panic!("Unexpected value {value:?}"),
}
}
fn len(&self) -> usize {
self.builder.len()
}
fn finish(&mut self) -> Arc<dyn Array> {
Arc::new(self.builder.finish())
}
}
#[derive(Default)]
struct SolArrayBuilderString {
builder: array::StringBuilder,
}
impl SolArrayBuilder for SolArrayBuilderString {
fn append_value(&mut self, value: &DynSolValue) {
match value {
DynSolValue::Address(v) => self.builder.append_value(v.encode_hex_with_prefix()),
DynSolValue::String(v) => self.builder.append_value(v),
DynSolValue::Uint(v, _) => self.builder.append_value(v.to_string()),
DynSolValue::Int(v, _) => self.builder.append_value(v.to_string()),
_ => panic!("Unexpected value {value:?}"),
}
}
fn len(&self) -> usize {
self.builder.len()
}
fn finish(&mut self) -> Arc<dyn Array> {
Arc::new(self.builder.finish())
}
}
#[derive(Default)]
struct SolArrayBuilderBytes {
builder: array::BinaryBuilder,
}
impl SolArrayBuilder for SolArrayBuilderBytes {
fn append_value(&mut self, value: &DynSolValue) {
match value {
DynSolValue::Bytes(v) => self.builder.append_value(v),
DynSolValue::FixedBytes(v, _) => self.builder.append_value(v.as_slice()),
_ => panic!("Unexpected value {value:?}"),
}
}
fn len(&self) -> usize {
self.builder.len()
}
fn finish(&mut self) -> Arc<dyn Array> {
Arc::new(self.builder.finish())
}
}
#[cfg(test)]
mod tests {
use super::*;
use alloy_primitives::{Address, B256, I256, U256};
use arrow::array::{
BinaryArray, BooleanArray, Int8Array, Int16Array, Int32Array, Int64Array, StringArray,
UInt8Array, UInt16Array, UInt32Array, UInt64Array,
};
#[test]
fn test_bool_builder_basic() {
let mut b = SolArrayBuilderBool::default();
assert!(b.is_empty());
b.append_value(&DynSolValue::Bool(true));
b.append_value(&DynSolValue::Bool(false));
b.append_value(&DynSolValue::Bool(true));
assert_eq!(b.len(), 3);
let arr = b.finish();
let arr = arr.as_any().downcast_ref::<BooleanArray>().unwrap();
assert!(arr.value(0));
assert!(!arr.value(1));
assert!(arr.value(2));
}
#[test]
#[should_panic(expected = "Unexpected value")]
fn test_bool_builder_wrong_type() {
let mut b = SolArrayBuilderBool::default();
b.append_value(&DynSolValue::Uint(U256::from(1), 8));
}
#[test]
fn test_int8_builder_basic() {
let mut b = SolArrayBuilderInt8::default();
b.append_value(&DynSolValue::Int(I256::try_from(42i8).unwrap(), 8));
b.append_value(&DynSolValue::Int(I256::try_from(-1i8).unwrap(), 8));
b.append_value(&DynSolValue::Int(I256::try_from(i8::MAX).unwrap(), 8));
b.append_value(&DynSolValue::Int(I256::try_from(i8::MIN).unwrap(), 8));
assert_eq!(b.len(), 4);
let arr = b.finish();
let arr = arr.as_any().downcast_ref::<Int8Array>().unwrap();
assert_eq!(arr.value(0), 42);
assert_eq!(arr.value(1), -1);
assert_eq!(arr.value(2), i8::MAX);
assert_eq!(arr.value(3), i8::MIN);
}
#[test]
fn test_int8_builder_overflow_truncates() {
let mut b = SolArrayBuilderInt8::default();
b.append_value(&DynSolValue::Int(I256::try_from(256i32).unwrap(), 8));
assert_eq!(b.len(), 1);
let arr = b.finish();
let arr = arr.as_any().downcast_ref::<Int8Array>().unwrap();
assert_eq!(arr.value(0), 0); }
#[test]
fn test_int16_builder_basic() {
let mut b = SolArrayBuilderInt16::default();
b.append_value(&DynSolValue::Int(I256::try_from(1000i16).unwrap(), 16));
b.append_value(&DynSolValue::Int(I256::try_from(-1000i16).unwrap(), 16));
b.append_value(&DynSolValue::Int(I256::try_from(i16::MAX).unwrap(), 16));
b.append_value(&DynSolValue::Int(I256::try_from(i16::MIN).unwrap(), 16));
assert_eq!(b.len(), 4);
let arr = b.finish();
let arr = arr.as_any().downcast_ref::<Int16Array>().unwrap();
assert_eq!(arr.value(0), 1000);
assert_eq!(arr.value(1), -1000);
assert_eq!(arr.value(2), i16::MAX);
assert_eq!(arr.value(3), i16::MIN);
}
#[test]
fn test_int16_builder_overflow_truncates() {
let mut b = SolArrayBuilderInt16::default();
b.append_value(&DynSolValue::Int(I256::try_from(65536i32).unwrap(), 16));
assert_eq!(b.len(), 1);
let arr = b.finish();
let arr = arr.as_any().downcast_ref::<Int16Array>().unwrap();
assert_eq!(arr.value(0), 0); }
#[test]
fn test_int32_builder_basic() {
let mut b = SolArrayBuilderInt32::default();
b.append_value(&DynSolValue::Int(I256::try_from(100_000i32).unwrap(), 24));
b.append_value(&DynSolValue::Int(I256::try_from(-100_000i32).unwrap(), 24));
b.append_value(&DynSolValue::Int(I256::try_from(i32::MAX).unwrap(), 32));
b.append_value(&DynSolValue::Int(I256::try_from(i32::MIN).unwrap(), 32));
assert_eq!(b.len(), 4);
let arr = b.finish();
let arr = arr.as_any().downcast_ref::<Int32Array>().unwrap();
assert_eq!(arr.value(0), 100_000);
assert_eq!(arr.value(1), -100_000);
assert_eq!(arr.value(2), i32::MAX);
assert_eq!(arr.value(3), i32::MIN);
}
#[test]
fn test_int32_builder_overflow_truncates() {
let mut b = SolArrayBuilderInt32::default();
let huge = I256::from_raw(U256::from_be_bytes(
"0x000000000000000000000000a9b1758a3e74e440c774e4cd7d7c00d9c5d27859"
.parse::<B256>()
.unwrap()
.0,
));
b.append_value(&DynSolValue::Int(huge, 24));
assert_eq!(b.len(), 1);
let arr = b.finish();
let arr = arr.as_any().downcast_ref::<Int32Array>().unwrap();
assert_eq!(arr.value(0), 0xc5d27859_u32 as i32);
}
#[test]
fn test_int64_builder_basic() {
let mut b = SolArrayBuilderInt64::default();
b.append_value(&DynSolValue::Int(I256::try_from(i64::MAX).unwrap(), 64));
b.append_value(&DynSolValue::Int(I256::try_from(i64::MIN).unwrap(), 64));
b.append_value(&DynSolValue::Int(I256::ZERO, 64));
b.append_value(&DynSolValue::Int(I256::MINUS_ONE, 64));
assert_eq!(b.len(), 4);
let arr = b.finish();
let arr = arr.as_any().downcast_ref::<Int64Array>().unwrap();
assert_eq!(arr.value(0), i64::MAX);
assert_eq!(arr.value(1), i64::MIN);
assert_eq!(arr.value(2), 0);
assert_eq!(arr.value(3), -1);
}
#[test]
fn test_int64_builder_overflow_truncates() {
let mut b = SolArrayBuilderInt64::default();
let huge = I256::try_from(u128::from(u64::MAX) + 1).unwrap();
b.append_value(&DynSolValue::Int(huge, 64));
assert_eq!(b.len(), 1);
let arr = b.finish();
let arr = arr.as_any().downcast_ref::<Int64Array>().unwrap();
assert_eq!(arr.value(0), 0);
}
#[test]
#[should_panic(expected = "Unexpected value")]
fn test_int32_builder_wrong_type() {
let mut b = SolArrayBuilderInt32::default();
b.append_value(&DynSolValue::Bool(true));
}
#[test]
fn test_uint8_builder_basic() {
let mut b = SolArrayBuilderUInt8::default();
b.append_value(&DynSolValue::Uint(U256::from(0), 8));
b.append_value(&DynSolValue::Uint(U256::from(255), 8));
b.append_value(&DynSolValue::Uint(U256::from(42), 8));
assert_eq!(b.len(), 3);
let arr = b.finish();
let arr = arr.as_any().downcast_ref::<UInt8Array>().unwrap();
assert_eq!(arr.value(0), 0);
assert_eq!(arr.value(1), 255);
assert_eq!(arr.value(2), 42);
}
#[test]
fn test_uint8_builder_overflow_truncates() {
let mut b = SolArrayBuilderUInt8::default();
b.append_value(&DynSolValue::Uint(U256::from(256), 8));
let arr = b.finish();
let arr = arr.as_any().downcast_ref::<UInt8Array>().unwrap();
assert_eq!(arr.value(0), 0); }
#[test]
fn test_uint16_builder_basic() {
let mut b = SolArrayBuilderUInt16::default();
b.append_value(&DynSolValue::Uint(U256::from(0), 16));
b.append_value(&DynSolValue::Uint(U256::from(u16::MAX), 16));
b.append_value(&DynSolValue::Uint(U256::from(1000), 16));
assert_eq!(b.len(), 3);
let arr = b.finish();
let arr = arr.as_any().downcast_ref::<UInt16Array>().unwrap();
assert_eq!(arr.value(0), 0);
assert_eq!(arr.value(1), u16::MAX);
assert_eq!(arr.value(2), 1000);
}
#[test]
fn test_uint16_builder_overflow_truncates() {
let mut b = SolArrayBuilderUInt16::default();
b.append_value(&DynSolValue::Uint(U256::from(0x1_0000u32), 16));
let arr = b.finish();
let arr = arr.as_any().downcast_ref::<UInt16Array>().unwrap();
assert_eq!(arr.value(0), 0);
}
#[test]
fn test_uint32_builder_basic() {
let mut b = SolArrayBuilderUInt32::default();
b.append_value(&DynSolValue::Uint(U256::from(0), 32));
b.append_value(&DynSolValue::Uint(U256::from(u32::MAX), 32));
b.append_value(&DynSolValue::Uint(U256::from(123456), 32));
assert_eq!(b.len(), 3);
let arr = b.finish();
let arr = arr.as_any().downcast_ref::<UInt32Array>().unwrap();
assert_eq!(arr.value(0), 0);
assert_eq!(arr.value(1), u32::MAX);
assert_eq!(arr.value(2), 123456);
}
#[test]
fn test_uint32_builder_overflow_truncates() {
let mut b = SolArrayBuilderUInt32::default();
b.append_value(&DynSolValue::Uint(U256::from(0x1_0000_0000u64), 32));
let arr = b.finish();
let arr = arr.as_any().downcast_ref::<UInt32Array>().unwrap();
assert_eq!(arr.value(0), 0);
}
#[test]
fn test_uint64_builder_basic() {
let mut b = SolArrayBuilderUInt64::default();
b.append_value(&DynSolValue::Uint(U256::from(0), 64));
b.append_value(&DynSolValue::Uint(U256::from(u64::MAX), 64));
b.append_value(&DynSolValue::Uint(U256::from(42), 64));
assert_eq!(b.len(), 3);
let arr = b.finish();
let arr = arr.as_any().downcast_ref::<UInt64Array>().unwrap();
assert_eq!(arr.value(0), 0);
assert_eq!(arr.value(1), u64::MAX);
assert_eq!(arr.value(2), 42);
}
#[test]
fn test_uint64_builder_overflow_truncates() {
let mut b = SolArrayBuilderUInt64::default();
b.append_value(&DynSolValue::Uint(U256::from(1u128 << 64), 64));
let arr = b.finish();
let arr = arr.as_any().downcast_ref::<UInt64Array>().unwrap();
assert_eq!(arr.value(0), 0);
}
#[test]
#[should_panic(expected = "Unexpected value")]
fn test_uint32_builder_wrong_type() {
let mut b = SolArrayBuilderUInt32::default();
b.append_value(&DynSolValue::Bool(false));
}
#[test]
fn test_string_builder_address() {
let mut b = SolArrayBuilderString::default();
let addr: Address = "0xdead000000000000000000000000000000000001"
.parse()
.unwrap();
b.append_value(&DynSolValue::Address(addr));
assert_eq!(b.len(), 1);
let arr = b.finish();
let arr = arr.as_any().downcast_ref::<StringArray>().unwrap();
assert_eq!(arr.value(0), "0xdead000000000000000000000000000000000001");
}
#[test]
fn test_string_builder_string() {
let mut b = SolArrayBuilderString::default();
b.append_value(&DynSolValue::String("hello world".to_string()));
let arr = b.finish();
let arr = arr.as_any().downcast_ref::<StringArray>().unwrap();
assert_eq!(arr.value(0), "hello world");
}
#[test]
fn test_string_builder_large_uint() {
let mut b = SolArrayBuilderString::default();
let big = U256::from(u128::MAX);
b.append_value(&DynSolValue::Uint(big, 128));
let arr = b.finish();
let arr = arr.as_any().downcast_ref::<StringArray>().unwrap();
assert_eq!(arr.value(0), u128::MAX.to_string());
}
#[test]
fn test_string_builder_large_int() {
let mut b = SolArrayBuilderString::default();
b.append_value(&DynSolValue::Int(I256::MINUS_ONE, 128));
let arr = b.finish();
let arr = arr.as_any().downcast_ref::<StringArray>().unwrap();
assert_eq!(arr.value(0), "-1");
}
#[test]
#[should_panic(expected = "Unexpected value")]
fn test_string_builder_wrong_type() {
let mut b = SolArrayBuilderString::default();
b.append_value(&DynSolValue::Bool(true));
}
#[test]
fn test_bytes_builder_dynamic() {
let mut b = SolArrayBuilderBytes::default();
b.append_value(&DynSolValue::Bytes(vec![0xde, 0xad, 0xbe, 0xef]));
assert_eq!(b.len(), 1);
let arr = b.finish();
let arr = arr.as_any().downcast_ref::<BinaryArray>().unwrap();
assert_eq!(arr.value(0), &[0xde, 0xad, 0xbe, 0xef]);
}
#[test]
fn test_bytes_builder_fixed() {
let mut b = SolArrayBuilderBytes::default();
let mut word = B256::ZERO;
word.0[..4].copy_from_slice(&[0x01, 0x02, 0x03, 0x04]);
b.append_value(&DynSolValue::FixedBytes(word, 4));
let arr = b.finish();
let arr = arr.as_any().downcast_ref::<BinaryArray>().unwrap();
assert_eq!(&arr.value(0)[..4], &[0x01, 0x02, 0x03, 0x04]);
}
#[test]
#[should_panic(expected = "Unexpected value")]
fn test_bytes_builder_wrong_type() {
let mut b = SolArrayBuilderBytes::default();
b.append_value(&DynSolValue::Uint(U256::from(1), 8));
}
#[test]
fn test_type_mapping_int_sizes() {
let mut b = dyn_sol_type_to_array_builder(&DynSolType::Int(8));
b.append_value(&DynSolValue::Int(I256::try_from(-1i8).unwrap(), 8));
let arr = b.finish();
assert!(arr.as_any().is::<Int8Array>());
let mut b = dyn_sol_type_to_array_builder(&DynSolType::Int(16));
b.append_value(&DynSolValue::Int(I256::try_from(-1i8).unwrap(), 16));
let arr = b.finish();
assert!(arr.as_any().is::<Int16Array>());
let mut b = dyn_sol_type_to_array_builder(&DynSolType::Int(24));
b.append_value(&DynSolValue::Int(I256::try_from(-1i8).unwrap(), 24));
let arr = b.finish();
assert!(arr.as_any().is::<Int32Array>());
let mut b = dyn_sol_type_to_array_builder(&DynSolType::Int(32));
b.append_value(&DynSolValue::Int(I256::try_from(-1i8).unwrap(), 32));
let arr = b.finish();
assert!(arr.as_any().is::<Int32Array>());
let mut b = dyn_sol_type_to_array_builder(&DynSolType::Int(64));
b.append_value(&DynSolValue::Int(I256::try_from(-1i8).unwrap(), 64));
let arr = b.finish();
assert!(arr.as_any().is::<Int64Array>());
let mut b = dyn_sol_type_to_array_builder(&DynSolType::Int(128));
b.append_value(&DynSolValue::Int(I256::try_from(-1i8).unwrap(), 128));
let arr = b.finish();
assert!(arr.as_any().is::<StringArray>());
let mut b = dyn_sol_type_to_array_builder(&DynSolType::Int(256));
b.append_value(&DynSolValue::Int(I256::try_from(-1i8).unwrap(), 256));
let arr = b.finish();
assert!(arr.as_any().is::<StringArray>());
}
#[test]
fn test_type_mapping_uint_sizes() {
let mut b = dyn_sol_type_to_array_builder(&DynSolType::Uint(8));
b.append_value(&DynSolValue::Uint(U256::from(1), 8));
let arr = b.finish();
assert!(arr.as_any().is::<UInt8Array>());
let mut b = dyn_sol_type_to_array_builder(&DynSolType::Uint(16));
b.append_value(&DynSolValue::Uint(U256::from(1), 16));
let arr = b.finish();
assert!(arr.as_any().is::<UInt16Array>());
let mut b = dyn_sol_type_to_array_builder(&DynSolType::Uint(32));
b.append_value(&DynSolValue::Uint(U256::from(1), 32));
let arr = b.finish();
assert!(arr.as_any().is::<UInt32Array>());
let mut b = dyn_sol_type_to_array_builder(&DynSolType::Uint(64));
b.append_value(&DynSolValue::Uint(U256::from(1), 64));
let arr = b.finish();
assert!(arr.as_any().is::<UInt64Array>());
let mut b = dyn_sol_type_to_array_builder(&DynSolType::Uint(128));
b.append_value(&DynSolValue::Uint(U256::from(1), 128));
let arr = b.finish();
assert!(arr.as_any().is::<StringArray>());
}
#[test]
fn test_type_mapping_non_numeric() {
let mut b = dyn_sol_type_to_array_builder(&DynSolType::Bool);
b.append_value(&DynSolValue::Bool(true));
let arr = b.finish();
assert!(arr.as_any().is::<BooleanArray>());
let mut b = dyn_sol_type_to_array_builder(&DynSolType::Address);
let addr: Address = "0x0000000000000000000000000000000000000001"
.parse()
.unwrap();
b.append_value(&DynSolValue::Address(addr));
let arr = b.finish();
assert!(arr.as_any().is::<StringArray>());
let mut b = dyn_sol_type_to_array_builder(&DynSolType::Bytes);
b.append_value(&DynSolValue::Bytes(vec![1]));
let arr = b.finish();
assert!(arr.as_any().is::<BinaryArray>());
let mut b = dyn_sol_type_to_array_builder(&DynSolType::FixedBytes(32));
b.append_value(&DynSolValue::FixedBytes(B256::ZERO, 32));
let arr = b.finish();
assert!(arr.as_any().is::<BinaryArray>());
}
#[test]
fn test_builder_resets_after_finish() {
let mut b = SolArrayBuilderUInt32::default();
b.append_value(&DynSolValue::Uint(U256::from(1), 32));
b.append_value(&DynSolValue::Uint(U256::from(2), 32));
assert_eq!(b.len(), 2);
let arr = b.finish();
let arr = arr.as_any().downcast_ref::<UInt32Array>().unwrap();
assert_eq!(arr.len(), 2);
assert_eq!(b.len(), 0);
b.append_value(&DynSolValue::Uint(U256::from(3), 32));
assert_eq!(b.len(), 1);
let arr = b.finish();
let arr = arr.as_any().downcast_ref::<UInt32Array>().unwrap();
assert_eq!(arr.len(), 1);
assert_eq!(arr.value(0), 3);
}
}