git.delta.rocks / unique-network / refs/commits / 15e4512df81d

difftreelog

source

crates/evm-coder/src/custom_signature.rs8.6 KiBsourcehistory
1use core::str::from_utf8;23pub const SIGNATURE_SIZE_LIMIT: usize = 256;45pub trait Name {6	const SIGNATURE: [u8; SIGNATURE_SIZE_LIMIT];7	const SIGNATURE_LEN: usize;89	fn name() -> &'static str {10		from_utf8(&Self::SIGNATURE[..Self::SIGNATURE_LEN]).expect("bad utf-8")11	}12}1314#[derive(Debug)]15pub struct FunctionSignature {16	pub signature: [u8; SIGNATURE_SIZE_LIMIT],17	pub signature_len: usize,18}1920impl FunctionSignature {21	pub const fn new(name: &'static FunctionName) -> FunctionSignature {22		let mut signature = [0_u8; SIGNATURE_SIZE_LIMIT];23		let name_len = name.signature_len;24		let name = name.signature;25		let mut dst_offset = 0;26		let bracket_open = {27			let mut b = [0_u8; SIGNATURE_SIZE_LIMIT];28			b[0] = b"("[0];29			b30		};31		crate::make_signature!(@copy(name, signature, name_len, dst_offset));32		crate::make_signature!(@copy(bracket_open, signature, 1, dst_offset));33		FunctionSignature {34			signature,35			signature_len: dst_offset,36		}37	}3839	pub const fn add_param(40		signature: FunctionSignature,41		param: ([u8; SIGNATURE_SIZE_LIMIT], usize),42	) -> FunctionSignature {43		let mut dst = signature.signature;44		let mut dst_offset = signature.signature_len;45		let (param_name, param_len) = param;46		let comma = {47			let mut b = [0_u8; SIGNATURE_SIZE_LIMIT];48			b[0] = b","[0];49			b50		};51		FunctionSignature {52			signature: {53				crate::make_signature!(@copy(param_name, dst, param_len, dst_offset));54				crate::make_signature!(@copy(comma, dst, 1, dst_offset));55				dst56			},57			signature_len: dst_offset,58		}59	}6061	pub const fn done(signature: FunctionSignature, owerride: bool) -> FunctionSignature {62		let mut dst = signature.signature;63		let mut dst_offset = signature.signature_len - if owerride { 1 } else { 0 };64		let bracket_close = {65			let mut b = [0_u8; SIGNATURE_SIZE_LIMIT];66			b[0] = b")"[0];67			b68		};69		FunctionSignature {70			signature: {71				crate::make_signature!(@copy(bracket_close, dst, 1, dst_offset));72				dst73			},74			signature_len: dst_offset,75		}76	}7778	// fn as_str(&self) -> &'static str {79	// 	from_utf8(&self.signature[..self.signature_len]).expect("bad utf-8")80	// }81}8283#[derive(Debug)]84pub struct FunctionName {85	signature: [u8; SIGNATURE_SIZE_LIMIT],86	signature_len: usize,87}8889impl FunctionName {90	pub const fn new(name: &'static str) -> FunctionName {91		let mut signature = [0_u8; SIGNATURE_SIZE_LIMIT];92		let name = name.as_bytes();93		let name_len = name.len();94		let mut dst_offset = 0;95		crate::make_signature!(@copy(name, signature, name_len, dst_offset));96		FunctionName {97			signature,98			signature_len: name_len,99		}100	}101}102103#[macro_export]104#[allow(missing_docs)]105macro_rules! make_signature { // May be "define_signature"?106	(new fn($func:expr)$(,)+) => {107		{108			let fs = FunctionSignature::new(& $func);109			let fs = FunctionSignature::done(fs, false);110			fs111		}112	};113	(new fn($func:expr), $($tt:tt)*) => {114		{115			let fs = FunctionSignature::new(& $func);116			let fs = make_signature!(@param; fs, $($tt),*);117			fs118		}119	};120121	(@param; $func:expr) => {122		FunctionSignature::done($func, true)123	};124	(@param; $func:expr, $param:expr) => {125		make_signature!(@param; FunctionSignature::add_param($func, $param))126	};127	(@param; $func:expr, $param:expr, $($tt:tt),*) => {128		make_signature!(@param; FunctionSignature::add_param($func, $param), $($tt),*)129	};130131    (new $($tt:tt)*) => {132        const SIGNATURE: [u8; SIGNATURE_SIZE_LIMIT] = {133            let mut out = [0u8; SIGNATURE_SIZE_LIMIT];134            let mut dst_offset = 0;135            make_signature!(@data(out, dst_offset); $($tt)*);136            out137        };138        const SIGNATURE_LEN: usize = 0 + make_signature!(@size; $($tt)*);139    };140141	// (@bytes)142143    (@size;) => {144        0145    };146    (@size; fixed($expr:expr) $($tt:tt)*) => {147        $expr.len() + make_signature!(@size; $($tt)*)148    };149    (@size; nameof($expr:ty) $($tt:tt)*) => {150        <$expr>::SIGNATURE_LEN + make_signature!(@size; $($tt)*)151    };152153    (@data($dst:ident, $dst_offset:ident);) => {};154    (@data($dst:ident, $dst_offset:ident); fixed($expr:expr) $($tt:tt)*) => {155        {156            let data = $expr.as_bytes();157			let data_len = data.len();158			make_signature!(@copy(data, $dst, data_len, $dst_offset));159        }160        make_signature!(@data($dst, $dst_offset); $($tt)*)161    };162    (@data($dst:ident, $dst_offset:ident); nameof($expr:ty) $($tt:tt)*) => {163        {164			let data = &<$expr>::SIGNATURE;165			let data_len = <$expr>::SIGNATURE_LEN;166            make_signature!(@copy(data, $dst, data_len, $dst_offset));167        }168        make_signature!(@data($dst, $dst_offset); $($tt)*)169    };170171	(@copy($src:ident, $dst:ident, $src_len:expr, $dst_offset:ident)) => {172		{173			let mut src_offset = 0;174			let src_len: usize = $src_len;175			while src_offset < src_len {176				$dst[$dst_offset] = $src[src_offset];177				$dst_offset += 1;178				src_offset += 1;179			}180		}181	}182}183184#[cfg(test)]185mod test {186	use core::str::from_utf8;187188	use frame_support::sp_runtime::app_crypto::sp_core::hexdisplay::AsBytesRef;189190	use super::{Name, SIGNATURE_SIZE_LIMIT, FunctionName, FunctionSignature};191192	impl Name for u8 {193		make_signature!(new fixed("uint8"));194	}195	impl Name for u32 {196		make_signature!(new fixed("uint32"));197	}198	impl<T: Name> Name for Vec<T> {199		make_signature!(new nameof(T) fixed("[]"));200	}201	impl<A: Name, B: Name> Name for (A, B) {202		make_signature!(new fixed("(") nameof(A) fixed(",") nameof(B) fixed(")"));203	}204205	struct MaxSize();206	impl Name for MaxSize {207		const SIGNATURE: [u8; SIGNATURE_SIZE_LIMIT] = [b'!'; SIGNATURE_SIZE_LIMIT];208		const SIGNATURE_LEN: usize = SIGNATURE_SIZE_LIMIT;209	}210211	#[test]212	fn simple() {213		assert_eq!(u8::name(), "uint8");214		assert_eq!(u32::name(), "uint32");215	}216217	#[test]218	fn vector_of_simple() {219		assert_eq!(<Vec<u8>>::name(), "uint8[]");220		assert_eq!(<Vec<u32>>::name(), "uint32[]");221	}222223	#[test]224	fn vector_of_vector() {225		assert_eq!(<Vec<Vec<u8>>>::name(), "uint8[][]");226	}227228	#[test]229	fn tuple_of_simple() {230		assert_eq!(<(u32, u8)>::name(), "(uint32,uint8)");231	}232233	#[test]234	fn tuple_of_tuple() {235		assert_eq!(236			<((u32, u8), (u8, u32))>::name(),237			"((uint32,uint8),(uint8,uint32))"238		);239	}240241	#[test]242	fn vector_of_tuple() {243		assert_eq!(<Vec<(u32, u8)>>::name(), "(uint32,uint8)[]");244	}245246	#[test]247	fn tuple_of_vector() {248		assert_eq!(<(Vec<u32>, u8)>::name(), "(uint32[],uint8)");249	}250251	#[test]252	fn complex() {253		assert_eq!(254			<(Vec<u32>, (u32, Vec<u8>))>::name(),255			"(uint32[],(uint32,uint8[]))"256		);257	}258259	#[test]260	fn max_size() {261		assert_eq!(<MaxSize>::name(), "!".repeat(SIGNATURE_SIZE_LIMIT));262	}263264	// This test must NOT compile!265	// #[test]266	// fn over_max_size() {267	// 	assert_eq!(<Vec<MaxSize>>::name(), "!".repeat(SIZE_LIMIT) + "[]");268	// }269270	#[test]271	fn make_func_without_args() {272		const SOME_FUNK_NAME: FunctionName = FunctionName::new("some_funk");273		const SIG: FunctionSignature = make_signature!(274			new fn(&SOME_FUNK_NAME),275		);276		let name = from_utf8(&SIG.signature[..SIG.signature_len]).unwrap();277		assert_eq!(name, "some_funk()");278	}279280	#[test]281	fn make_func_with_1_args() {282		const SOME_FUNK_NAME: FunctionName = FunctionName::new("some_funk");283		const SIG: FunctionSignature = make_signature!(284			new fn(&SOME_FUNK_NAME),285			(u8::SIGNATURE, u8::SIGNATURE_LEN)286		);287		let name = from_utf8(&SIG.signature[..SIG.signature_len]).unwrap();288		assert_eq!(name, "some_funk(uint8)");289	}290291	#[test]292	fn make_func_with_2_args() {293		const SOME_FUNK_NAME: FunctionName = FunctionName::new("some_funk");294		const SIG: FunctionSignature = make_signature!(295			new fn(&SOME_FUNK_NAME),296			(u8::SIGNATURE, u8::SIGNATURE_LEN)297			(<Vec<u32>>::SIGNATURE, <Vec<u32>>::SIGNATURE_LEN)298		);299		let name = from_utf8(&SIG.signature[..SIG.signature_len]).unwrap();300		assert_eq!(name, "some_funk(uint8,uint32[])");301	}302303	#[test]304	fn make_func_with_3_args() {305		const SOME_FUNK_NAME: FunctionName = FunctionName::new("some_funk");306		const SIG: FunctionSignature = make_signature!(307			new fn(&SOME_FUNK_NAME),308			(u8::SIGNATURE, u8::SIGNATURE_LEN)309			(u32::SIGNATURE, u32::SIGNATURE_LEN)310			(<Vec<u32>>::SIGNATURE, <Vec<u32>>::SIGNATURE_LEN)311		);312		let name = from_utf8(&SIG.signature[..SIG.signature_len]).unwrap();313		assert_eq!(name, "some_funk(uint8,uint32,uint32[])");314	}315316	#[test]317	fn make_slice_from_signature() {318		const SOME_FUNK_NAME: FunctionName = FunctionName::new("some_funk");319		const SIG: FunctionSignature = make_signature!(320			new fn(&SOME_FUNK_NAME),321			(u8::SIGNATURE, u8::SIGNATURE_LEN)322			(u32::SIGNATURE, u32::SIGNATURE_LEN)323			(<Vec<u32>>::SIGNATURE, <Vec<u32>>::SIGNATURE_LEN)324		);325		const NAME: [u8; SIG.signature_len] = {326			let mut name: [u8; SIG.signature_len] = [0; SIG.signature_len];327			let mut i = 0;328			while i < SIG.signature_len {329				name[i] = SIG.signature[i];330				i += 1;331			}332			name333		};334		assert_eq!(&NAME, b"some_funk(uint8,uint32,uint32[])");335	}336}