1#[cfg(not(feature = "std"))]2use alloc::{string::String};3use core::{fmt, marker::PhantomData};4use impl_trait_for_tuples::impl_for_tuples;5use crate::types::*;67pub trait SolidityTypeName: 'static {8 fn solidity_name(writer: &mut impl fmt::Write) -> fmt::Result;9 fn solidity_default(writer: &mut impl fmt::Write) -> fmt::Result;10 fn is_void() -> bool {11 false12 }13}1415macro_rules! solidity_type_name {16 ($($ty:ident => $name:literal = $default:literal),* $(,)?) => {17 $(18 impl SolidityTypeName for $ty {19 fn solidity_name(writer: &mut impl core::fmt::Write) -> core::fmt::Result {20 write!(writer, $name)21 }22 fn solidity_default(writer: &mut impl core::fmt::Write) -> core::fmt::Result {23 write!(writer, $default)24 }25 }26 )*27 };28}2930solidity_type_name! {31 uint8 => "uint8" = "0",32 uint32 => "uint32" = "0",33 uint128 => "uint128" = "0",34 uint256 => "uint256" = "0",35 address => "address" = "0x0000000000000000000000000000000000000000",36 string => "string memory" = "\"\"",37 bytes => "bytes memory" = "hex\"\"",38 bool => "bool" = "false",39}40impl SolidityTypeName for void {41 fn solidity_name(_writer: &mut impl fmt::Write) -> fmt::Result {42 Ok(())43 }44 fn solidity_default(_writer: &mut impl fmt::Write) -> fmt::Result {45 Ok(())46 }47 fn is_void() -> bool {48 true49 }50}5152pub trait SolidityArguments {53 fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result;54 fn solidity_get(&self, writer: &mut impl fmt::Write) -> fmt::Result;55 fn solidity_default(&self, writer: &mut impl fmt::Write) -> fmt::Result;56 fn is_empty(&self) -> bool {57 self.len() == 058 }59 fn len(&self) -> usize;60}6162#[derive(Default)]63pub struct UnnamedArgument<T>(PhantomData<*const T>);6465impl<T: SolidityTypeName> SolidityArguments for UnnamedArgument<T> {66 fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {67 if !T::is_void() {68 T::solidity_name(writer)69 } else {70 Ok(())71 }72 }73 fn solidity_get(&self, _writer: &mut impl fmt::Write) -> fmt::Result {74 Ok(())75 }76 fn solidity_default(&self, writer: &mut impl fmt::Write) -> fmt::Result {77 T::solidity_default(writer)78 }79 fn len(&self) -> usize {80 if T::is_void() {81 082 } else {83 184 }85 }86}8788pub struct NamedArgument<T>(&'static str, PhantomData<*const T>);8990impl<T> NamedArgument<T> {91 pub fn new(name: &'static str) -> Self {92 Self(name, Default::default())93 }94}9596impl<T: SolidityTypeName> SolidityArguments for NamedArgument<T> {97 fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {98 if !T::is_void() {99 T::solidity_name(writer)?;100 write!(writer, " {}", self.0)101 } else {102 Ok(())103 }104 }105 fn solidity_get(&self, writer: &mut impl fmt::Write) -> fmt::Result {106 writeln!(writer, "\t\t{};", self.0)107 }108 fn solidity_default(&self, writer: &mut impl fmt::Write) -> fmt::Result {109 T::solidity_default(writer)110 }111 fn len(&self) -> usize {112 if T::is_void() {113 0114 } else {115 1116 }117 }118}119120impl SolidityArguments for () {121 fn solidity_name(&self, _writer: &mut impl fmt::Write) -> fmt::Result {122 Ok(())123 }124 fn solidity_get(&self, _writer: &mut impl fmt::Write) -> fmt::Result {125 Ok(())126 }127 fn solidity_default(&self, _writer: &mut impl fmt::Write) -> fmt::Result {128 Ok(())129 }130 fn len(&self) -> usize {131 0132 }133}134135#[impl_for_tuples(1, 5)]136impl SolidityArguments for Tuple {137 for_tuples!( where #( Tuple: SolidityArguments ),* );138139 fn solidity_name(&self, writer: &mut impl fmt::Write) -> fmt::Result {140 let mut first = true;141 for_tuples!( #(142 if !Tuple.is_empty() {143 if !first {144 write!(writer, ", ")?;145 }146 first = false;147 Tuple.solidity_name(writer)?;148 }149 )* );150 Ok(())151 }152 fn solidity_get(&self, writer: &mut impl fmt::Write) -> fmt::Result {153 for_tuples!( #(154 Tuple.solidity_get(writer)?;155 )* );156 Ok(())157 }158 fn solidity_default(&self, writer: &mut impl fmt::Write) -> fmt::Result {159 if self.is_empty() {160 Ok(())161 } else if self.len() == 1 {162 for_tuples!( #(163 Tuple.solidity_default(writer)?;164 )* );165 Ok(())166 } else {167 write!(writer, "(")?;168 let mut first = true;169 for_tuples!( #(170 if !Tuple.is_empty() {171 if !first {172 write!(writer, ", ")?;173 }174 first = false;175 Tuple.solidity_name(writer)?;176 }177 )* );178 write!(writer, ")")?;179 Ok(())180 }181 }182 fn len(&self) -> usize {183 for_tuples!( #( Tuple.len() )+* )184 }185}186187pub trait SolidityFunctions {188 fn solidity_name(&self, is_impl: bool, writer: &mut impl fmt::Write) -> fmt::Result;189}190191pub enum SolidityMutability {192 Pure,193 View,194 Mutable,195}196pub struct SolidityFunction<A, R> {197 pub name: &'static str,198 pub args: A,199 pub result: R,200 pub mutability: SolidityMutability,201}202impl<A: SolidityArguments, R: SolidityArguments> SolidityFunctions for SolidityFunction<A, R> {203 fn solidity_name(&self, is_impl: bool, writer: &mut impl fmt::Write) -> fmt::Result {204 write!(writer, "\tfunction {}(", self.name)?;205 self.args.solidity_name(writer)?;206 write!(writer, ")")?;207 if is_impl {208 write!(writer, " public")?;209 } else {210 write!(writer, " external")?;211 }212 match &self.mutability {213 SolidityMutability::Pure => write!(writer, " pure")?,214 SolidityMutability::View => write!(writer, " view")?,215 SolidityMutability::Mutable => {}216 }217 if !self.result.is_empty() {218 write!(writer, " returns (")?;219 self.result.solidity_name(writer)?;220 write!(writer, ")")?;221 }222 if is_impl {223 writeln!(writer, " {{")?;224 writeln!(writer, "\t\trequire(false, stub_error);")?;225 self.args.solidity_get(writer)?;226 match &self.mutability {227 SolidityMutability::Pure => {}228 SolidityMutability::View => writeln!(writer, "\t\tdummy;")?,229 SolidityMutability::Mutable => writeln!(writer, "\t\tdummy = 0;")?,230 }231 if !self.result.is_empty() {232 write!(writer, "\t\treturn ")?;233 self.result.solidity_default(writer)?;234 writeln!(writer, ";")?;235 }236 writeln!(writer, "\t}}")?;237 } else {238 writeln!(writer, ";")?;239 }240 Ok(())241 }242}243244#[impl_for_tuples(0, 12)]245impl SolidityFunctions for Tuple {246 for_tuples!( where #( Tuple: SolidityFunctions ),* );247248 fn solidity_name(&self, is_impl: bool, writer: &mut impl fmt::Write) -> fmt::Result {249 let mut first = false;250 for_tuples!( #(251 Tuple.solidity_name(is_impl, writer)?;252 )* );253 Ok(())254 }255}256257pub struct SolidityInterface<F: SolidityFunctions> {258 pub name: &'static str,259 pub is: &'static [&'static str],260 pub functions: F,261}262263impl<F: SolidityFunctions> SolidityInterface<F> {264 pub fn format(&self, is_impl: bool, out: &mut impl fmt::Write) -> fmt::Result {265 if is_impl {266 write!(out, "contract ")?;267 } else {268 write!(out, "interface ")?;269 }270 write!(out, "{}", self.name)?;271 if !self.is.is_empty() {272 write!(out, " is")?;273 for (i, n) in self.is.iter().enumerate() {274 if i != 0 {275 write!(out, ",")?;276 }277 write!(out, " {}", n)?;278 }279 }280 writeln!(out, " {{")?;281 self.functions.solidity_name(is_impl, out)?;282 writeln!(out, "}}")?;283 Ok(())284 }285}286287pub struct SolidityEvent<A> {288 pub name: &'static str,289 pub args: A,290}291292impl<A: SolidityArguments> SolidityFunctions for SolidityEvent<A> {293 fn solidity_name(&self, _is_impl: bool, writer: &mut impl fmt::Write) -> fmt::Result {294 write!(writer, "\tevent {}(", self.name)?;295 self.args.solidity_name(writer)?;296 writeln!(writer, ");")297 }298}