git.delta.rocks / unique-network / refs/commits / 2e0d1a668d33

difftreelog

source

crates/evm-coder/src/abi/impls.rs7.6 KiBsourcehistory
1use crate::{2	execution::{Result, ResultWithPostInfo, WithPostDispatchInfo},3	types::*,4	make_signature,5	custom_signature::SignatureUnit,6};7use super::{traits::*, ABI_ALIGNMENT, AbiReader, AbiWriter};8use primitive_types::{U256, H160};910#[cfg(not(feature = "std"))]11use alloc::vec::Vec;1213macro_rules! impl_abi_readable {14	($ty:ty, $method:ident, $dynamic:literal) => {15		impl sealed::CanBePlacedInVec for $ty {}1617		impl AbiType for $ty {18			const SIGNATURE: SignatureUnit = make_signature!(new fixed(stringify!($ty)));1920			fn is_dynamic() -> bool {21				$dynamic22			}2324			fn size() -> usize {25				ABI_ALIGNMENT26			}27		}2829		impl AbiRead for $ty {30			fn abi_read(reader: &mut AbiReader) -> Result<$ty> {31				reader.$method()32			}33		}34	};35}3637impl_abi_readable!(uint32, uint32, false);38impl_abi_readable!(uint64, uint64, false);39impl_abi_readable!(uint128, uint128, false);40impl_abi_readable!(uint256, uint256, false);41impl_abi_readable!(bytes4, bytes4, false);42impl_abi_readable!(address, address, false);43impl_abi_readable!(string, string, true);4445impl sealed::CanBePlacedInVec for bool {}4647impl AbiType for bool {48	const SIGNATURE: SignatureUnit = make_signature!(new fixed("bool"));4950	fn is_dynamic() -> bool {51		false52	}53	fn size() -> usize {54		ABI_ALIGNMENT55	}56}57impl AbiRead for bool {58	fn abi_read(reader: &mut AbiReader) -> Result<bool> {59		reader.bool()60	}61}6263impl AbiType for uint8 {64	const SIGNATURE: SignatureUnit = make_signature!(new fixed("uint8"));6566	fn is_dynamic() -> bool {67		false68	}69	fn size() -> usize {70		ABI_ALIGNMENT71	}72}73impl AbiRead for uint8 {74	fn abi_read(reader: &mut AbiReader) -> Result<uint8> {75		reader.uint8()76	}77}7879impl AbiType for bytes {80	const SIGNATURE: SignatureUnit = make_signature!(new fixed("bytes"));8182	fn is_dynamic() -> bool {83		true84	}85	fn size() -> usize {86		ABI_ALIGNMENT87	}88}89impl AbiRead for bytes {90	fn abi_read(reader: &mut AbiReader) -> Result<bytes> {91		Ok(bytes(reader.bytes()?))92	}93}9495impl<R: AbiRead + sealed::CanBePlacedInVec> AbiRead for Vec<R> {96	fn abi_read(reader: &mut AbiReader) -> Result<Vec<R>> {97		let mut sub = reader.subresult(None)?;98		let size = sub.uint32()? as usize;99		sub.subresult_offset = sub.offset;100		let mut out = Vec::with_capacity(size);101		for _ in 0..size {102			out.push(<R>::abi_read(&mut sub)?);103		}104		Ok(out)105	}106}107108impl<R: AbiType> AbiType for Vec<R> {109	const SIGNATURE: SignatureUnit = make_signature!(new nameof(R::SIGNATURE) fixed("[]"));110111	fn is_dynamic() -> bool {112		true113	}114115	fn size() -> usize {116		ABI_ALIGNMENT117	}118}119120impl sealed::CanBePlacedInVec for EthCrossAccount {}121122impl AbiType for EthCrossAccount {123	const SIGNATURE: SignatureUnit = make_signature!(new fixed("(address,uint256)"));124125	fn is_dynamic() -> bool {126		address::is_dynamic() || uint256::is_dynamic()127	}128129	fn size() -> usize {130		<address as AbiType>::size() + <uint256 as AbiType>::size()131	}132}133134impl AbiRead for EthCrossAccount {135	fn abi_read(reader: &mut AbiReader) -> Result<EthCrossAccount> {136		let size = if !EthCrossAccount::is_dynamic() {137			Some(<EthCrossAccount as AbiType>::size())138		} else {139			None140		};141		let mut subresult = reader.subresult(size)?;142		let eth = <address>::abi_read(&mut subresult)?;143		let sub = <uint256>::abi_read(&mut subresult)?;144145		Ok(EthCrossAccount { eth, sub })146	}147}148149impl AbiWrite for EthCrossAccount {150	fn abi_write(&self, writer: &mut AbiWriter) {151		self.eth.abi_write(writer);152		self.sub.abi_write(writer);153	}154}155156impl sealed::CanBePlacedInVec for Property {}157158impl AbiType for Property {159	const SIGNATURE: SignatureUnit = make_signature!(new fixed("(string,bytes)"));160161	fn is_dynamic() -> bool {162		string::is_dynamic() || bytes::is_dynamic()163	}164165	fn size() -> usize {166		<string as AbiType>::size() + <bytes as AbiType>::size()167	}168}169170impl AbiRead for Property {171	fn abi_read(reader: &mut AbiReader) -> Result<Property> {172		let size = if !Property::is_dynamic() {173			Some(<Property as AbiType>::size())174		} else {175			None176		};177		let mut subresult = reader.subresult(size)?;178		let key = <string>::abi_read(&mut subresult)?;179		let value = <bytes>::abi_read(&mut subresult)?;180181		Ok(Property { key, value })182	}183}184185impl AbiWrite for Property {186	fn abi_write(&self, writer: &mut AbiWriter) {187		self.key.abi_write(writer);188		self.value.abi_write(writer);189	}190}191192macro_rules! impl_abi_writeable {193	($ty:ty, $method:ident) => {194		impl AbiWrite for $ty {195			fn abi_write(&self, writer: &mut AbiWriter) {196				writer.$method(&self)197			}198		}199	};200}201202impl_abi_writeable!(u8, uint8);203impl_abi_writeable!(u32, uint32);204impl_abi_writeable!(u128, uint128);205impl_abi_writeable!(U256, uint256);206impl_abi_writeable!(H160, address);207impl_abi_writeable!(bool, bool);208impl_abi_writeable!(&str, string);209210impl AbiWrite for string {211	fn abi_write(&self, writer: &mut AbiWriter) {212		writer.string(self)213	}214}215216impl AbiWrite for bytes {217	fn abi_write(&self, writer: &mut AbiWriter) {218		writer.bytes(self.0.as_slice())219	}220}221222impl<T: AbiWrite + AbiType> AbiWrite for Vec<T> {223	fn abi_write(&self, writer: &mut AbiWriter) {224		let is_dynamic = T::is_dynamic();225		let mut sub = if is_dynamic {226			AbiWriter::new_dynamic(is_dynamic)227		} else {228			AbiWriter::new()229		};230231		// Write items count232		(self.len() as u32).abi_write(&mut sub);233234		for item in self {235			item.abi_write(&mut sub);236		}237		writer.write_subresult(sub);238	}239}240241impl AbiWrite for () {242	fn abi_write(&self, _writer: &mut AbiWriter) {}243}244245/// This particular AbiWrite implementation should be split to another trait,246/// which only implements `to_result`, but due to lack of specialization feature247/// in stable Rust, we can't have blanket impl of this trait `for T where T: AbiWrite`,248/// so here we abusing default trait methods for it249impl<T: AbiWrite> AbiWrite for ResultWithPostInfo<T> {250	fn abi_write(&self, _writer: &mut AbiWriter) {251		debug_assert!(false, "shouldn't be called, see comment")252	}253	fn to_result(&self) -> ResultWithPostInfo<AbiWriter> {254		match self {255			Ok(v) => Ok(WithPostDispatchInfo {256				post_info: v.post_info.clone(),257				data: {258					let mut out = AbiWriter::new();259					v.data.abi_write(&mut out);260					out261				},262			}),263			Err(e) => Err(e.clone()),264		}265	}266}267268macro_rules! impl_tuples {269	($($ident:ident)+) => {270		impl<$($ident: AbiType,)+> AbiType for ($($ident,)+)271		where272        $(273            $ident: AbiType,274        )+275		{276            const SIGNATURE: SignatureUnit = make_signature!(277                new fixed("(")278                $(nameof(<$ident>::SIGNATURE) fixed(","))+279                shift_left(1)280                fixed(")")281            );282283			fn is_dynamic() -> bool {284				false285				$(286					|| <$ident>::is_dynamic()287				)*288			}289290			fn size() -> usize {291				0 $(+ <$ident>::size())+292			}293		}294295		impl<$($ident),+> sealed::CanBePlacedInVec for ($($ident,)+) {}296297		impl<$($ident),+> AbiRead for ($($ident,)+)298		where299			$($ident: AbiRead,)+300			($($ident,)+): AbiType,301		{302			fn abi_read(reader: &mut AbiReader) -> Result<($($ident,)+)> {303				let size = if !<($($ident,)+)>::is_dynamic() { Some(<($($ident,)+)>::size()) } else { None };304				let mut subresult = reader.subresult(size)?;305				Ok((306					$(<$ident>::abi_read(&mut subresult)?,)+307				))308			}309		}310311		#[allow(non_snake_case)]312		impl<$($ident),+> AbiWrite for ($($ident,)+)313		where314			$($ident: AbiWrite,)+315		{316			fn abi_write(&self, writer: &mut AbiWriter) {317				let ($($ident,)+) = self;318				if writer.is_dynamic {319					let mut sub = AbiWriter::new();320					$($ident.abi_write(&mut sub);)+321					writer.write_subresult(sub);322				} else {323					$($ident.abi_write(writer);)+324				}325			}326		}327	};328}329330impl_tuples! {A}331impl_tuples! {A B}332impl_tuples! {A B C}333impl_tuples! {A B C D}334impl_tuples! {A B C D E}335impl_tuples! {A B C D E F}336impl_tuples! {A B C D E F G}337impl_tuples! {A B C D E F G H}338impl_tuples! {A B C D E F G H I}339impl_tuples! {A B C D E F G H I J}