// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see .
// Rust/Parity ABI struct autogenerator.
// By Gav Wood, 2016.
String.prototype.replaceAll = function(f, t) { return this.split(f).join(t); }
String.prototype.toSnake = function(){
return this.replace(/([A-Z])/g, function($1){return "_"+$1.toLowerCase();});
};
function makeContractFile(name, json, prefs) {
return `// Autogenerated from JSON contract definition using Rust contract convertor.
#![allow(unused_imports)]
use std::string::String;
use std::result::Result;
use std::fmt;
use {util, ethabi};
use util::{FixedHash, Uint};
${convertContract(name, json, prefs)}
`;
}
function convertContract(name, json, prefs) {
return `${prefs._pub ? "pub " : ""}struct ${name} {
contract: ethabi::Contract,
address: util::Address,
do_call: Box) -> Result, String> + Send ${prefs._sync ? "+ Sync " : ""}+ 'static>,
}
impl ${name} {
pub fn new(address: util::Address, do_call: F) -> Self where F: Fn(util::Address, Vec) -> Result, String> + Send ${prefs._sync ? "+ Sync " : ""}+ 'static {
${name} {
contract: ethabi::Contract::new(ethabi::Interface::load(b"${JSON.stringify(json.filter(a => a.type == 'function')).replaceAll('"', '\\"')}").expect("JSON is autogenerated; qed")),
address: address,
do_call: Box::new(do_call),
}
}
fn as_string(e: T) -> String { format!("{:?}", e) }
${json.filter(x => x.type == 'function').map(x => convertFunction(x, prefs)).join("\n")}
}`;
}
function mapType(name, type, _prefs) {
let prefs = _prefs || {};
var m;
if ((m = type.match(/^bytes(\d+)$/)) != null && m[1] <= 32) {
if (prefs['string'])
return `&str`;
else
return `&util::H${m[1] * 8}`;
}
if ((m = type.match(/^(u?)int(\d+)$/)) != null) {
var n = [8, 16, 32, 64, 128, 160, 256].filter(i => m[2] <= i)[0];
if (n) {
if (n <= 64)
return `${m[1] == 'u' ? 'u' : 'i'}${n}`;
if (m[1] == 'u')
return `util::U${n}`;
// ERROR - unsupported integer (signed > 32 or unsigned > 256)
}
}
if (type == "address")
return "&util::Address";
if (type == "bool")
return "bool";
if (type == "string")
return "&str";
if (type == "bytes")
return "&[u8]";
console.log(`Unsupported argument type: ${type} (${name})`);
}
function mapReturnType(name, type, _prefs) {
let prefs = _prefs || {};
var m;
if ((m = type.match(/^bytes(\d+)$/)) != null && m[1] <= 32) {
if (prefs['string'])
return `String`;
else
return `util::H${m[1] * 8}`;
}
if ((m = type.match(/^(u?)int(\d+)$/)) != null) {
var n = [8, 16, 32, 64, 128, 160, 256].filter(i => m[2] <= i)[0];
if (n) {
if (n <= 64)
return `${m[1] == 'u' ? 'u' : 'i'}${n}`;
if (m[1] == 'u')
return `util::U${n}`;
// ERROR - unsupported integer (signed > 32 or unsigned > 256)
}
}
if (type == "address")
return "util::Address";
if (type == "bool")
return "bool";
if (type == "string")
return "String";
if (type == "bytes")
return "Vec";
if (type == "address[]")
return "Vec";
console.log(`Unsupported return type: ${type} (${name})`);
}
function convertToken(name, type, _prefs) {
let prefs = _prefs || {};
var m;
if ((m = type.match(/^bytes(\d+)$/)) != null && m[1] <= 32) {
if (prefs['string'])
return `ethabi::Token::FixedBytes(${name}.as_bytes().to_owned())`;
else
return `ethabi::Token::FixedBytes(${name}.as_ref().to_owned())`;
}
if ((m = type.match(/^(u?)int(\d+)$/)) != null) {
var n = [8, 16, 32, 64, 128, 160, 256].filter(i => m[2] <= i)[0];
if (n) {
if (m[1] == 'u')
return `ethabi::Token::Uint({ let mut r = [0u8; 32]; ${n <= 64 ? "util::U256::from(" + name + " as u64)" : name}.to_big_endian(&mut r); r })`;
else if (n <= 32)
return `ethabi::Token::Int(pad_i32(${name} as i32))`;
// ERROR - unsupported integer (signed > 32 or unsigned > 256)
}
}
if (type == "address")
return `ethabi::Token::Address(${name}.clone().0)`;
if (type == "bool")
return `ethabi::Token::Bool(${name})`;
if (type == "string")
return `ethabi::Token::String(${name}.to_owned())`;
if (type == "bytes")
return `ethabi::Token::Bytes(${name}.to_owned())`;
console.log(`Unsupported argument type: ${type} (${name})`);
}
function tokenType(name, type, _prefs) {
let prefs = _prefs || {};
var m;
if ((m = type.match(/^bytes(\d+)$/)) != null && m[1] <= 32)
return `${name}.to_fixed_bytes()`;
if ((m = type.match(/^(u?)int(\d+)$/)) != null) {
return `${name}.to_${m[1]}int()`;
}
if (type == "address")
return `${name}.to_address()`;
if (type == "bool")
return `${name}.to_bool()`;
if (type == "string")
return `${name}.to_string()`;
if (type == "bytes")
return `${name}.to_bytes()`;
if (type == "address[]")
return `${name}.to_array().and_then(|v| v.into_iter().map(|a| a.to_address()).collect::