1use core::{fmt, marker::PhantomData};2use impl_trait_for_tuples::impl_for_tuples;3use crate::types::*;45pub trait SolidityTypeName: 'static {6 fn solidity_name(writer: &mut impl fmt::Write) -> fmt::Result;7 fn is_void() -> bool {8 false9 }10}1112macro_rules! solidity_type_name {13 ($($ty:ident => $name:expr),* $(,)?) => {14 $(15 impl SolidityTypeName for $ty {16 fn solidity_name(writer: &mut impl core::fmt::Write) -> core::fmt::Result {17 write!(writer, $name)18 }19 }20 )*21 };22}2324solidity_type_name! {25 uint8 => "uint8",26 address => "address",27 string => "memory string",28}29impl SolidityTypeName for void {30 fn solidity_name(_writer: &mut impl fmt::Write) -> fmt::Result {31 Ok(())32 }33 fn is_void() -> bool {34 true35 }36}3738pub trait SolidityArguments {39 fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result;40 fn is_empty(&self) -> bool {41 self.len() == 042 }43 fn len(&self) -> usize;44}4546pub struct UnnamedArgument<T>(PhantomData<*const T>);4748impl<T: SolidityTypeName> SolidityArguments for UnnamedArgument<T> {49 fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {50 if !T::is_void() {51 T::solidity_name(writer)52 } else {53 Ok(())54 }55 }56 fn len(&self) -> usize {57 if T::is_void() {58 059 } else {60 161 }62 }63}6465pub struct NamedArgument<T>(&'static str, PhantomData<*const T>);6667impl<T: SolidityTypeName> SolidityArguments for NamedArgument<T> {68 fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {69 if !T::is_void() {70 T::solidity_name(writer)?;71 write!(writer, " {}", self.0)72 } else {73 Ok(())74 }75 }76 fn len(&self) -> usize {77 if T::is_void() {78 079 } else {80 181 }82 }83}8485impl SolidityArguments for () {86 fn solidity_name(&self, _writer: &mut impl fmt::Write) -> fmt::Result {87 Ok(())88 }89 fn len(&self) -> usize {90 091 }92}9394#[impl_for_tuples(1, 5)]95impl SolidityArguments for Tuple {96 for_tuples!( where #( Tuple: SolidityArguments ),* );9798 fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {99 let mut first = false;100 for_tuples!( #(101 if !Tuple.is_empty() {102 if first {103 write!(writer, ", ")?;104 }105 first = false;106 Tuple.solidity_name(writer)?;107 }108 )* );109 Ok(())110 }111 fn len(&self) -> usize {112 for_tuples!( #( Tuple.len() )+* )113 }114}115116trait SolidityFunctions {117 fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result;118}119120pub enum SolidityMutability {121 Pure,122 View,123 Mutable,124}125pub struct SolidityFunction<A, R> {126 name: &'static str,127 args: A,128 result: R,129 mutability: SolidityMutability,130}131impl<A: SolidityArguments, R: SolidityArguments> SolidityFunctions for SolidityFunction<A, R> {132 fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {133 write!(writer, "function {}(", self.name)?;134 self.args.solidity_name(writer)?;135 write!(writer, ") public")?;136 match &self.mutability {137 SolidityMutability::Pure => write!(writer, " pure")?,138 SolidityMutability::View => write!(writer, " view")?,139 SolidityMutability::Mutable => {}140 }141 if !self.result.is_empty() {142 write!(writer, "returns (")?;143 self.result.solidity_name(writer)?;144 write!(writer, ")")?;145 }146 writeln!(writer, ";")147 }148}149150#[impl_for_tuples(0, 12)]151impl SolidityFunctions for Tuple {152 for_tuples!( where #( Tuple: SolidityFunctions ),* );153154 fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {155 let mut first = false;156 for_tuples!( #(157 Tuple.solidity_name(writer)?;158 )* );159 Ok(())160 }161}