use super::*;
use crate::solidity::revert::InjectBacktrace;
use impl_trait_for_tuples::impl_for_tuples;
use sp_core::{ConstU32, Get, H160};
impl Codec for () {
fn read(_reader: &mut Reader) -> MayRevert<Self> {
Ok(())
}
fn write(_writer: &mut Writer, _value: Self) {}
fn has_static_size() -> bool {
true
}
fn signature() -> String {
String::from("()")
}
}
#[impl_for_tuples(1, 18)]
impl Codec for Tuple {
fn has_static_size() -> bool {
for_tuples!(#( Tuple::has_static_size() )&*)
}
fn read(reader: &mut Reader) -> MayRevert<Self> {
if Self::has_static_size() {
let mut index = 0;
Ok(for_tuples!( ( #( {
let elem = reader.read::<Tuple>().in_tuple(index)?;
index +=1;
elem
} ),* ) ))
} else {
let reader = &mut reader.read_pointer()?;
let mut index = 0;
Ok(for_tuples!( ( #( {
let elem = reader.read::<Tuple>().in_tuple(index)?;
index +=1;
elem
} ),* ) ))
}
}
fn write(writer: &mut Writer, value: Self) {
if Self::has_static_size() {
for_tuples!( #( Tuple::write(writer, value.Tuple); )* );
} else {
let mut inner_writer = Writer::new();
for_tuples!( #( Tuple::write(&mut inner_writer, value.Tuple); )* );
writer.write_pointer(inner_writer.build());
}
}
fn signature() -> String {
let mut subtypes = Vec::new();
for_tuples!( #( subtypes.push(Tuple::signature()); )* );
alloc::format!("({})", subtypes.join(","))
}
fn is_explicit_tuple() -> bool {
true
}
}
impl Codec for H256 {
fn read(reader: &mut Reader) -> MayRevert<Self> {
let range = reader.move_cursor(32)?;
let data = reader
.input
.get(range)
.ok_or_else(|| RevertReason::read_out_of_bounds("bytes32"))?;
Ok(H256::from_slice(data))
}
fn write(writer: &mut Writer, value: Self) {
writer.data.extend_from_slice(value.as_bytes());
}
fn has_static_size() -> bool {
true
}
fn signature() -> String {
String::from("bytes32")
}
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct Address(pub H160);
impl From<H160> for Address {
fn from(a: H160) -> Address {
Address(a)
}
}
impl From<Address> for H160 {
fn from(a: Address) -> H160 {
a.0
}
}
impl Address {
pub fn as_u64(&self) -> Option<u64> {
let _u64 = self.0.to_low_u64_be();
if self.0 == H160::from_low_u64_be(_u64) {
Some(_u64)
} else {
None
}
}
}
impl Codec for Address {
fn read(reader: &mut Reader) -> MayRevert<Self> {
let range = reader.move_cursor(32)?;
let data = reader
.input
.get(range)
.ok_or_else(|| RevertReason::read_out_of_bounds("address"))?;
Ok(H160::from_slice(&data[12..32]).into())
}
fn write(writer: &mut Writer, value: Self) {
H256::write(writer, value.0.into());
}
fn has_static_size() -> bool {
true
}
fn signature() -> String {
String::from("address")
}
}
impl Codec for U256 {
fn read(reader: &mut Reader) -> MayRevert<Self> {
let range = reader.move_cursor(32)?;
let data = reader
.input
.get(range)
.ok_or_else(|| RevertReason::read_out_of_bounds("uint256"))?;
Ok(U256::from_big_endian(data))
}
fn write(writer: &mut Writer, value: Self) {
let mut buffer = [0u8; 32];
value.to_big_endian(&mut buffer);
writer.data.extend_from_slice(&buffer);
}
fn has_static_size() -> bool {
true
}
fn signature() -> String {
String::from("uint256")
}
}
macro_rules! impl_evmdata_for_uints {
($($uint:ty, )*) => {
$(
impl Codec for $uint {
fn read(reader: &mut Reader) -> MayRevert<Self> {
let value256: U256 = reader.read()
.map_err(|_| RevertReason::read_out_of_bounds(
Self::signature()
))?;
value256
.try_into()
.map_err(|_| RevertReason::value_is_too_large(
Self::signature()
).into())
}
fn write(writer: &mut Writer, value: Self) {
U256::write(writer, value.into());
}
fn has_static_size() -> bool {
true
}
fn signature() -> String {
alloc::format!("uint{}", core::mem::size_of::<Self>() * 8)
}
}
)*
};
}
impl_evmdata_for_uints!(u8, u16, u32, u64, u128,);
impl Codec for bool {
fn read(reader: &mut Reader) -> MayRevert<Self> {
let h256 = H256::read(reader).map_err(|_| RevertReason::read_out_of_bounds("bool"))?;
Ok(!h256.is_zero())
}
fn write(writer: &mut Writer, value: Self) {
let mut buffer = [0u8; 32];
if value {
buffer[31] = 1;
}
writer.data.extend_from_slice(&buffer);
}
fn has_static_size() -> bool {
true
}
fn signature() -> String {
String::from("bool")
}
}
type ConstU32Max = ConstU32<{ u32::MAX }>;
impl<T: Codec> Codec for Vec<T> {
fn read(reader: &mut Reader) -> MayRevert<Self> {
BoundedVec::<T, ConstU32Max>::read(reader).map(|x| x.into())
}
fn write(writer: &mut Writer, value: Self) {
BoundedVec::<T, ConstU32Max>::write(
writer,
BoundedVec {
inner: value,
_phantom: PhantomData,
},
)
}
fn has_static_size() -> bool {
false
}
fn signature() -> String {
alloc::format!("{}[]", T::signature())
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct BoundedVec<T, S> {
inner: Vec<T>,
_phantom: PhantomData<S>,
}
impl<T: Codec, S: Get<u32>> Codec for BoundedVec<T, S> {
fn read(reader: &mut Reader) -> MayRevert<Self> {
let mut inner_reader = reader.read_pointer()?;
let array_size: usize = inner_reader
.read::<U256>()
.map_err(|_| RevertReason::read_out_of_bounds("length"))?
.try_into()
.map_err(|_| RevertReason::value_is_too_large("length"))?;
if array_size > S::get() as usize {
return Err(RevertReason::value_is_too_large("length").into());
}
let mut array = vec![];
let mut item_reader = Reader {
input: inner_reader
.input
.get(32..)
.ok_or_else(|| RevertReason::read_out_of_bounds("array content"))?,
cursor: 0,
};
for i in 0..array_size {
array.push(item_reader.read().in_array(i)?);
}
Ok(BoundedVec {
inner: array,
_phantom: PhantomData,
})
}
fn write(writer: &mut Writer, value: Self) {
let value: Vec<_> = value.into();
let mut inner_writer = Writer::new().write(U256::from(value.len()));
for inner in value {
let shift = inner_writer.data.len();
let item_writer = Writer::new().write(inner);
inner_writer = inner_writer.write_raw_bytes(&item_writer.data);
for mut offset_datum in item_writer.offset_data {
offset_datum.offset_shift += 32;
offset_datum.offset_position += shift;
inner_writer.offset_data.push(offset_datum);
}
}
writer.write_pointer(inner_writer.build());
}
fn has_static_size() -> bool {
false
}
fn signature() -> String {
alloc::format!("{}[]", T::signature())
}
}
impl<T, S> From<Vec<T>> for BoundedVec<T, S> {
fn from(value: Vec<T>) -> Self {
BoundedVec {
inner: value,
_phantom: PhantomData,
}
}
}
impl<T: Clone, S> From<&[T]> for BoundedVec<T, S> {
fn from(value: &[T]) -> Self {
BoundedVec {
inner: value.to_vec(),
_phantom: PhantomData,
}
}
}
impl<T: Clone, S, const N: usize> From<[T; N]> for BoundedVec<T, S> {
fn from(value: [T; N]) -> Self {
BoundedVec {
inner: value.to_vec(),
_phantom: PhantomData,
}
}
}
impl<T, S> From<BoundedVec<T, S>> for Vec<T> {
fn from(value: BoundedVec<T, S>) -> Self {
value.inner
}
}