difftreelog
refactor remove AbiType
in: master
3 files changed
crates/evm-coder/procedural/src/lib.rsdiffbeforeafterboth107 if path.segments.len() != 1 {107 if path.segments.len() != 1 {108 return Err(syn::Error::new(108 return Err(syn::Error::new(109 path.span(),109 path.span(),110 "expected path to have only segment",110 "expected path to have only one segment",111 ));111 ));112 }112 }113 let last_segment = &path.segments.last().unwrap();113 let last_segment = &path.segments.last().unwrap();crates/evm-coder/procedural/src/solidity_interface.rsdiffbeforeafterboth329 }329 }330}330}331331332#[derive(Debug)]333enum AbiType {332trait AbiType {334 // type335 Plain(Ident),333 fn plain(&self) -> syn::Result<&Ident>;336 // (type1,type2)337 Tuple(Vec<AbiType>),334 fn is_value(&self) -> bool;338 // type[]339 Vec(Box<AbiType>),335 fn is_caller(&self) -> bool;340 // type[20]341 Array(Box<AbiType>, usize),336 fn is_special(&self) -> bool;342}337}338343impl AbiType {339impl AbiType for Type {344 fn try_from(value: &Type) -> syn::Result<Self> {345 let value = Self::try_maybe_special_from(value)?;346 if value.is_special() {347 return Err(syn::Error::new(value.span(), "unexpected special type"));348 }349 Ok(value)350 }351 fn try_maybe_special_from(value: &Type) -> syn::Result<Self> {340 fn plain(&self) -> syn::Result<&Ident> {352 match value {353 Type::Array(arr) => {354 let wrapped = AbiType::try_from(&arr.elem)?;355 match &arr.len {356 Expr::Lit(l) => match &l.lit {357 Lit::Int(i) => {358 let num = i.base10_parse::<usize>()?;359 Ok(AbiType::Array(Box::new(wrapped), num as usize))360 }361 _ => Err(syn::Error::new(arr.len.span(), "should be int literal")),362 },363 _ => Err(syn::Error::new(arr.len.span(), "should be literal")),364 }365 }366 Type::Path(_) => {367 let path = parse_path(value)?;341 let path = parse_path(self)?;368 let segment = parse_path_segment(path)?;342 let segment = parse_path_segment(path)?;369 if segment.ident == "Vec" {343 if !segment.arguments.is_empty() {370 let args = match &segment.arguments {371 PathArguments::AngleBracketed(e) => e,372 _ => {373 return Err(syn::Error::new(374 segment.arguments.span(),375 "missing Vec generic",376 ))377 }378 };379 let args = &args.args;380 if args.len() != 1 {381 return Err(syn::Error::new(382 args.span(),383 "expected only one generic for vec",384 ));385 }386 let arg = args.first().expect("first arg");387388 let ty = match arg {389 GenericArgument::Type(ty) => ty,390 _ => {391 return Err(syn::Error::new(392 arg.span(),393 "expected first generic to be type",394 ))395 }396 };397398 let wrapped = AbiType::try_from(ty)?;399 Ok(Self::Vec(Box::new(wrapped)))400 } else {401 if !segment.arguments.is_empty() {402 return Err(syn::Error::new(344 return Err(syn::Error::new(self.span(), "Not plain type"));403 segment.arguments.span(),404 "unexpected generic arguments for non-vec type",405 ));406 }345 }407 Ok(Self::Plain(segment.ident.clone()))346 Ok(&segment.ident)408 }409 }347 }410 Type::Tuple(t) => {348411 let mut out = Vec::with_capacity(t.elems.len());412 for el in t.elems.iter() {413 out.push(AbiType::try_from(el)?)414 }415 Ok(Self::Tuple(out))416 }417 _ => Err(syn::Error::new(418 value.span(),419 "unexpected type, only arrays, plain types and tuples are supported",420 )),421 }422 }423 fn is_value(&self) -> bool {349 fn is_value(&self) -> bool {424 matches!(self, Self::Plain(v) if v == "value")350 if let Ok(ident) = self.plain() {351 return ident == "value";352 }353 false425 }354 }355426 fn is_caller(&self) -> bool {356 fn is_caller(&self) -> bool {427 matches!(self, Self::Plain(v) if v == "caller")357 if let Ok(ident) = self.plain() {358 return ident == "caller";359 }360 false428 }361 }362429 fn is_special(&self) -> bool {363 fn is_special(&self) -> bool {430 self.is_caller() || self.is_value()364 self.is_caller() || self.is_value()431 }365 }432 fn selector_ty_buf(&self, buf: &mut String) -> std::fmt::Result {366}433 match self {434 AbiType::Plain(t) => {435 write!(buf, "{}", t)436 }437 AbiType::Tuple(t) => {438 write!(buf, "(")?;439 for (i, t) in t.iter().enumerate() {440 if i != 0 {441 write!(buf, ",")?;442 }443 t.selector_ty_buf(buf)?;444 }445 write!(buf, ")")446 }447 AbiType::Vec(v) => {448 v.selector_ty_buf(buf)?;449 write!(buf, "[]")450 }451 AbiType::Array(v, len) => {452 v.selector_ty_buf(buf)?;453 write!(buf, "[{}]", len)454 }455 }456 }457 fn selector_ty(&self) -> String {458 let mut out = String::new();459 self.selector_ty_buf(&mut out).expect("no fmt error");460 out461 }462}463impl ToTokens for AbiType {464 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {465 match self {466 AbiType::Plain(t) => tokens.extend(quote! {#t}),467 AbiType::Tuple(t) => {468 tokens.extend(quote! {(469 #(#t),*470 )});471 }472 AbiType::Vec(v) => tokens.extend(quote! {Vec<#v>}),473 AbiType::Array(v, l) => tokens.extend(quote! {[#v; #l]}),474 }475 }476}477367478#[derive(Debug)]368#[derive(Debug)]479struct MethodArg {369struct MethodArg {480 name: Ident,370 name: Ident,481 camel_name: String,371 camel_name: String,482 ty: AbiType,372 ty: Type,483}373}484impl MethodArg {374impl MethodArg {485 fn try_from(value: &PatType) -> syn::Result<Self> {375 fn try_from(value: &PatType) -> syn::Result<Self> {486 let name = parse_ident_from_pat(&value.pat)?.clone();376 let name = parse_ident_from_pat(&value.pat)?.clone();487 Ok(Self {377 Ok(Self {488 camel_name: cases::camelcase::to_camel_case(&name.to_string()),378 camel_name: cases::camelcase::to_camel_case(&name.to_string()),489 name,379 name,490 ty: AbiType::try_maybe_special_from(&value.ty)?,380 ty: value.ty.as_ref().clone(),491 })381 })492 }382 }493 fn is_value(&self) -> bool {383 fn is_value(&self) -> bool {499 fn is_special(&self) -> bool {389 fn is_special(&self) -> bool {500 self.ty.is_special()390 self.ty.is_special()501 }391 }502 fn selector_ty(&self) -> String {503 assert!(!self.is_special());504 self.ty.selector_ty()505 }506392507 fn expand_call_def(&self) -> proc_macro2::TokenStream {393 fn expand_call_def(&self) -> proc_macro2::TokenStream {508 assert!(!self.is_special());394 assert!(!self.is_special());578 camel_name: String,464 camel_name: String,579 pascal_name: Ident,465 pascal_name: Ident,580 screaming_name: Ident,466 screaming_name: Ident,581 selector_str: String,582 selector: u32,583 hide: bool,467 hide: bool,584 args: Vec<MethodArg>,468 args: Vec<MethodArg>,585 has_normal_args: bool,469 has_normal_args: bool,670 let camel_name = info554 let camel_name = info671 .rename_selector555 .rename_selector672 .unwrap_or_else(|| cases::camelcase::to_camel_case(&ident.to_string()));556 .unwrap_or_else(|| cases::camelcase::to_camel_case(&ident.to_string()));673 let mut selector_str = camel_name.clone();674 selector_str.push('(');675 let mut has_normal_args = false;557 let has_normal_args = args.iter().filter(|arg| !arg.is_special()).count() != 0;676 for (i, arg) in args.iter().filter(|arg| !arg.is_special()).enumerate() {677 if i != 0 {678 selector_str.push(',');679 }680 write!(selector_str, "{}", arg.selector_ty()).unwrap();681 has_normal_args = true;682 }683 let has_value_args = args.iter().any(|a| a.is_value());558 let has_value_args = args.iter().any(|a| a.is_value());684 selector_str.push(')');685 let selector = fn_selector_str(&selector_str);686559687 Ok(Self {560 Ok(Self {688 name: ident.clone(),561 name: ident.clone(),689 camel_name,562 camel_name,690 pascal_name: snake_ident_to_pascal(ident),563 pascal_name: snake_ident_to_pascal(ident),691 screaming_name: snake_ident_to_screaming(ident),564 screaming_name: snake_ident_to_screaming(ident),692 selector_str,693 selector,694 hide: info.hide,565 hide: info.hide,695 args,566 args,696 has_normal_args,567 has_normal_args,728 fn expand_const(&self) -> proc_macro2::TokenStream {599 fn expand_const(&self) -> proc_macro2::TokenStream {729 let screaming_name = &self.screaming_name;600 let screaming_name = &self.screaming_name;730 let screaming_name_signature = format_ident!("{}_SIGNATURE", &self.screaming_name);601 let screaming_name_signature = format_ident!("{}_SIGNATURE", &self.screaming_name);731 let selector_str = &self.selector_str;732 let custom_signature = self.expand_custom_signature();602 let custom_signature = self.expand_custom_signature();733 quote! {603 quote! {734 #[doc = #selector_str]735 const #screaming_name_signature: ::evm_coder::custom_signature::FunctionSignature = #custom_signature;604 const #screaming_name_signature: ::evm_coder::custom_signature::FunctionSignature = #custom_signature;736 const #screaming_name: ::evm_coder::types::bytes4 = {605 const #screaming_name: ::evm_coder::types::bytes4 = {737 let mut sum = ::evm_coder::sha3_const::Keccak256::new();606 let mut sum = ::evm_coder::sha3_const::Keccak256::new();845 }714 }846 }715 }847716848 fn expand_type(717 fn expand_type(ty: &Type, token_stream: &mut proc_macro2::TokenStream, read_signature: bool) {849 ty: &AbiType,850 token_stream: &mut proc_macro2::TokenStream,851 read_signature: bool,852 ) {853 match ty {718 match ty {854 AbiType::Plain(ref ident) => {719 Type::Path(tp) => {720 if let Some(qself) = &tp.qself {721 panic!("no receiver expected {:?}", qself.ty.span());722 }723 let path = &tp.path;724 if path.segments.len() != 1 {725 panic!("expected path to have only one segment {:?}", path.span());726 }727 let last_segment = path.segments.last().unwrap();728729 if last_segment.ident == "Vec" {730 let args = match &last_segment.arguments {731 PathArguments::AngleBracketed(e) => e,732 _ => {733 panic!("missing Vec generic {:?}", last_segment.arguments.span());734 }735 };736 let args = &args.args;737 if args.len() != 1 {738 panic!("expected only one generic for vec {:?}", args.span());739 }740 let arg = args.first().expect("first arg");741742 let ty = match arg {743 GenericArgument::Type(ty) => ty,744 _ => {745 panic!("expected first generic to be type {:?}", arg.span());746 }747 };748749 let mut vec_token = proc_macro2::TokenStream::new();750 Self::expand_type(ty, &mut vec_token, false);751 vec_token = if read_signature {752 quote! { (<Vec<#vec_token>>::SIGNATURE) }753 } else {754 quote! { <Vec<#vec_token>> }755 };756 token_stream.extend(vec_token);757 } else {758 if !last_segment.arguments.is_empty() {759 panic!(760 "unexpected generic arguments for non-vec type {:?}",761 last_segment.arguments.span()762 );763 }764765 let ident = &last_segment.ident;855 let plain_token = if read_signature {766 let plain_token = if read_signature {856 quote! {767 quote! {857 (<#ident>::SIGNATURE)768 (<#ident>::SIGNATURE)864775865 token_stream.extend(plain_token);776 token_stream.extend(plain_token);866 }777 }778 }867779868 AbiType::Tuple(ref tuple_type) => {780 Type::Tuple(tt) => {781 // for ty in tt.elems.iter() {782 // out.push(AbiType::try_from(ty)?)783 // }784869 let mut tuple_types = proc_macro2::TokenStream::new();785 let mut tuple_types = proc_macro2::TokenStream::new();870 let mut is_first = true;786 let mut is_first = true;871787872 for ty in tuple_type {788 for ty in tt.elems.iter() {873 if is_first {789 if is_first {874 is_first = false790 is_first = false875 } else {791 } else {885 token_stream.extend(tuple_types);801 token_stream.extend(tuple_types);886 }802 }887803888 AbiType::Vec(ref vec_type) => {804 // Type::Array(arr) => {889 let mut vec_token = proc_macro2::TokenStream::new();805 // let wrapped = AbiType::try_from(&arr.elem)?;890 Self::expand_type(vec_type.as_ref(), &mut vec_token, false);806 // match &arr.len {891 vec_token = if read_signature {807 // Expr::Lit(l) => match &l.lit {892 quote! { (<Vec<#vec_token>>::SIGNATURE) }808 // Lit::Int(i) => {893 } else {809 // let num = i.base10_parse::<usize>()?;894 quote! { <Vec<#vec_token>> }810 // Ok(AbiType::Array(Box::new(wrapped), num as usize))895 };811 // }896 token_stream.extend(vec_token);812 // _ => Err(syn::Error::new(arr.len.span(), "should be int literal")),897 }813 // },898814 // _ => Err(syn::Error::new(arr.len.span(), "should be literal")),815 // }816 // }899 AbiType::Array(_, _) => todo!("Array eth signature"),817 _ => panic!("Unexpected type {ty:?}"),900 };818 }819 // match ty {820 // AbiType::Plain(ref ident) => {821 // let plain_token = if read_signature {822 // quote! {823 // (<#ident>::SIGNATURE)824 // }825 // } else {826 // quote! {827 // #ident828 // }829 // };830831 // token_stream.extend(plain_token);832 // }833834 // AbiType::Tuple(ref tuple_type) => {835 // let mut tuple_types = proc_macro2::TokenStream::new();836 // let mut is_first = true;837838 // for ty in tuple_type {839 // if is_first {840 // is_first = false841 // } else {842 // tuple_types.extend(quote!(,));843 // }844 // Self::expand_type(ty, &mut tuple_types, false);845 // }846 // tuple_types = if read_signature {847 // quote! { (<(#tuple_types)>::SIGNATURE) }848 // } else {849 // quote! { (#tuple_types) }850 // };851 // token_stream.extend(tuple_types);852 // }853854 // AbiType::Vec(ref vec_type) => {855 // let mut vec_token = proc_macro2::TokenStream::new();856 // Self::expand_type(vec_type.as_ref(), &mut vec_token, false);857 // vec_token = if read_signature {858 // quote! { (<Vec<#vec_token>>::SIGNATURE) }859 // } else {860 // quote! { <Vec<#vec_token>> }861 // };862 // token_stream.extend(vec_token);863 // }864865 // AbiType::Array(_, _) => todo!("Array eth signature"),866 // };901 }867 }902868903 fn expand_custom_signature(&self) -> proc_macro2::TokenStream {869 fn expand_custom_signature(&self) -> proc_macro2::TokenStream {947 .filter(|a| !a.is_special())913 .filter(|a| !a.is_special())948 .map(MethodArg::expand_solidity_argument);914 .map(MethodArg::expand_solidity_argument);949 let docs = &self.docs;915 let docs = &self.docs;950 let selector_str = &self.selector_str;951 let screaming_name = &self.screaming_name;916 let screaming_name = &self.screaming_name;952 let hide = self.hide;917 let hide = self.hide;953 let custom_signature = self.expand_custom_signature();918 let custom_signature = self.expand_custom_signature();962 quote! {927 quote! {963 SolidityFunction {928 SolidityFunction {964 docs: &[#(#docs),*],929 docs: &[#(#docs),*],965 selector_str: #selector_str,966 hide: #hide,930 hide: #hide,967 selector: u32::from_be_bytes(Self::#screaming_name),931 selector: u32::from_be_bytes(Self::#screaming_name),968 custom_signature: #custom_signature,932 custom_signature: #custom_signature,crates/evm-coder/src/solidity.rsdiffbeforeafterboth484}484}485pub struct SolidityFunction<A, R> {485pub struct SolidityFunction<A, R> {486 pub docs: &'static [&'static str],486 pub docs: &'static [&'static str],487 pub selector_str: &'static str,488 pub selector: u32,487 pub selector: u32,489 pub hide: bool,488 pub hide: bool,490 pub custom_signature: FunctionSignature,489 pub custom_signature: FunctionSignature,510 "\t{hide_comment}/// @dev EVM selector for this function is: 0x{:0>8x},",509 "\t{hide_comment}/// @dev EVM selector for this function is: 0x{:0>8x},",511 self.selector510 self.selector512 )?;511 )?;513 writeln!(514 writer,515 "\t{hide_comment}/// or in textual repr: {}",516 self.selector_str517 )?;518 if self.selector_str != self.custom_signature.as_str() {519 writeln!(512 writeln!(520 writer,513 writer,521 "\t{hide_comment}/// or in the expanded repr: {}",514 "\t{hide_comment}/// or in textual repr: {}",522 self.custom_signature.as_str()515 self.custom_signature.as_str()523 )?;516 )?;524 }525 write!(writer, "\t{hide_comment}function {}(", self.name)?;517 write!(writer, "\t{hide_comment}function {}(", self.name)?;526 self.args.solidity_name(writer, tc)?;518 self.args.solidity_name(writer, tc)?;527 write!(writer, ")")?;519 write!(writer, ")")?;