Skip to content

Commit 6cc2423

Browse files
committed
Add SNAFU handlers for file operations
1 parent 62ee604 commit 6cc2423

File tree

3 files changed

+127
-40
lines changed

3 files changed

+127
-40
lines changed

Cargo.lock

Lines changed: 29 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@ sha3 = "0.10.6"
1616
itertools = "0.10.5"
1717
hex = "0.4.3"
1818
ethabi = "18.0.0"
19+
snafu = "0.7.3"

src/main.rs

Lines changed: 97 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
1-
use std::{io::{BufReader, self, BufRead, BufWriter, Write}, fs, collections::HashMap};
21
use ethabi::ParamType;
32
use hex::ToHex;
43
use serde::Serialize;
4+
use std::{
5+
collections::HashMap,
6+
fs,
7+
io::{self, BufRead, BufReader, BufWriter, Write},
8+
path::PathBuf,
9+
};
510

6-
use tinytemplate::{TinyTemplate, format_unescaped};
711
use clap::Parser;
812
use convert_case::{Case, Casing};
913
use itertools::Itertools;
1014
use sha3::{Digest, Keccak256};
15+
use snafu::prelude::*;
16+
use tinytemplate::{format_unescaped, TinyTemplate};
1117

1218
#[derive(Parser, Debug)]
1319
struct Args {
@@ -377,7 +383,8 @@ fn convert_type(ty: &ParamType) -> String {
377383
128 => "i128",
378384

379385
_ => "I256",
380-
}.to_owned(),
386+
}
387+
.to_owned(),
381388

382389
ParamType::Uint(size) => match size {
383390
8 => "u8",
@@ -387,20 +394,34 @@ fn convert_type(ty: &ParamType) -> String {
387394
128 => "u128",
388395

389396
_ => "U256",
390-
}.to_owned(),
397+
}
398+
.to_owned(),
391399
}
392400
}
393401

402+
#[derive(Debug, Snafu)]
403+
enum Error {
404+
#[snafu(display("Unable to open input file {}: {}", path.display(), source))]
405+
ReadInput { source: io::Error, path: PathBuf },
406+
407+
#[snafu(display("Unable to create output file {}: {}", path.display(), source))]
408+
WriteOutput { source: io::Error, path: PathBuf },
409+
}
410+
394411
fn main() -> Result<(), Box<dyn std::error::Error>> {
395412
let args = Args::parse();
396413

397414
let mut reader: Box<dyn BufRead> = match args.input {
398-
Some(filename) => Box::new(BufReader::new(fs::File::open(filename)?)),
415+
Some(filename) => Box::new(BufReader::new(
416+
fs::File::open(filename.clone()).context(ReadInputSnafu { path: filename })?,
417+
)),
399418
None => Box::new(BufReader::new(io::stdin())),
400419
};
401420

402421
let mut writer: Box<dyn Write> = match args.output {
403-
Some(filename) => Box::new(BufWriter::new(fs::File::create(filename)?)),
422+
Some(filename) => Box::new(BufWriter::new(
423+
fs::File::create(filename.clone()).context(WriteOutputSnafu { path: filename })?,
424+
)),
404425
None => Box::new(BufWriter::new(io::stdout())),
405426
};
406427

@@ -415,18 +436,33 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
415436
template.add_template("module", MODULE_TEMPLATE)?;
416437

417438
template.add_formatter("snake", |value, buf| match value {
418-
serde_json::Value::String(s) => { *buf += &s.to_case(Case::Snake); Ok(()) },
419-
_ => Err(tinytemplate::error::Error::GenericError { msg: "string value expected".to_owned() }),
439+
serde_json::Value::String(s) => {
440+
*buf += &s.to_case(Case::Snake);
441+
Ok(())
442+
}
443+
_ => Err(tinytemplate::error::Error::GenericError {
444+
msg: "string value expected".to_owned(),
445+
}),
420446
});
421447

422448
template.add_formatter("upper_snake", |value, buf| match value {
423-
serde_json::Value::String(s) => { *buf += &s.to_case(Case::UpperSnake); Ok(()) },
424-
_ => Err(tinytemplate::error::Error::GenericError { msg: "string value expected".to_owned() }),
449+
serde_json::Value::String(s) => {
450+
*buf += &s.to_case(Case::UpperSnake);
451+
Ok(())
452+
}
453+
_ => Err(tinytemplate::error::Error::GenericError {
454+
msg: "string value expected".to_owned(),
455+
}),
425456
});
426457

427458
template.add_formatter("upper_camel", |value, buf| match value {
428-
serde_json::Value::String(s) => { *buf += &s.to_case(Case::UpperCamel); Ok(()) },
429-
_ => Err(tinytemplate::error::Error::GenericError { msg: "string value expected".to_owned() }),
459+
serde_json::Value::String(s) => {
460+
*buf += &s.to_case(Case::UpperCamel);
461+
Ok(())
462+
}
463+
_ => Err(tinytemplate::error::Error::GenericError {
464+
msg: "string value expected".to_owned(),
465+
}),
430466
});
431467

432468
template.add_formatter("capitalize", |value, buf| match value {
@@ -437,8 +473,10 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
437473
*buf += tail;
438474

439475
Ok(())
440-
},
441-
_ => Err(tinytemplate::error::Error::GenericError { msg: "string value expected".to_owned() }),
476+
}
477+
_ => Err(tinytemplate::error::Error::GenericError {
478+
msg: "string value expected".to_owned(),
479+
}),
442480
});
443481

444482
template.add_formatter("ordinal", |value, buf| match value {
@@ -456,9 +494,11 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
456494
buf.push_str(ordinal);
457495

458496
Ok(())
459-
},
497+
}
460498

461-
_ => Err(tinytemplate::error::Error::GenericError { msg: "string value expected".to_owned() }),
499+
_ => Err(tinytemplate::error::Error::GenericError {
500+
msg: "string value expected".to_owned(),
501+
}),
462502
});
463503

464504
template.add_formatter("convert_type", |value, buf| match value {
@@ -468,18 +508,24 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
468508

469509
buf.push_str(&converted);
470510
Ok(())
471-
},
511+
}
472512

473-
_ => Err(tinytemplate::error::Error::GenericError { msg: "string value expected".to_owned() }),
513+
_ => Err(tinytemplate::error::Error::GenericError {
514+
msg: "string value expected".to_owned(),
515+
}),
474516
});
475517

476518
let mut is_overloaded = HashMap::new();
477519

478520
for function in parsed
479521
.members()
480-
.filter(|item| item["type"] == "function" )
481-
.filter(|item| item["stateMutability"] != "view" )
482-
.filter(|item| item["outputs"].members().all(|output| output["type"] == "bool"))
522+
.filter(|item| item["type"] == "function")
523+
.filter(|item| item["stateMutability"] != "view")
524+
.filter(|item| {
525+
item["outputs"]
526+
.members()
527+
.all(|output| output["type"] == "bool")
528+
})
483529
{
484530
let function_name = function["name"].as_str().unwrap();
485531

@@ -494,27 +540,35 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
494540

495541
for function in parsed
496542
.members()
497-
.filter(|item| item["type"] == "function" )
498-
.filter(|item| item["stateMutability"] != "view" )
499-
.filter(|item| item["outputs"].members().all(|output| output["type"] == "bool"))
543+
.filter(|item| item["type"] == "function")
544+
.filter(|item| item["stateMutability"] != "view")
545+
.filter(|item| {
546+
item["outputs"]
547+
.members()
548+
.all(|output| output["type"] == "bool")
549+
})
500550
{
501551
let function_name = function["name"].to_string();
502552

503-
let inputs: Vec<_> = function["inputs"].members().map(|m| {
504-
let raw_type = m["type"].as_str().unwrap();
505-
let param_type = ethabi::param_type::Reader::read(raw_type).unwrap();
506-
let converted = convert_type(&param_type);
507-
508-
Input {
509-
name: m["name"].to_string(),
510-
evm_type: raw_type.to_string(),
511-
rust_type: converted,
512-
}
513-
}).collect();
553+
let inputs: Vec<_> = function["inputs"]
554+
.members()
555+
.map(|m| {
556+
let raw_type = m["type"].as_str().unwrap();
557+
let param_type = ethabi::param_type::Reader::read(raw_type).unwrap();
558+
let converted = convert_type(&param_type);
559+
560+
Input {
561+
name: m["name"].to_string(),
562+
evm_type: raw_type.to_string(),
563+
rust_type: converted,
564+
}
565+
})
566+
.collect();
514567

515568
// let outputs: String = function["outputs"].members().map(|m| format!("{}: {}, ", m["name"], m["type"])).collect();
516569

517-
let selector = format!("{name}({args})",
570+
let selector = format!(
571+
"{name}({args})",
518572
name = function_name,
519573
args = inputs.iter().map(|input| input.evm_type.as_str()).join(","),
520574
);
@@ -526,12 +580,15 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
526580

527581
if is_overloaded[function_name.as_str()] {
528582
let function = {
529-
if let Some(function) = overloaded_functions.iter_mut().find(|f| f.name == function_name) {
583+
if let Some(function) = overloaded_functions
584+
.iter_mut()
585+
.find(|f| f.name == function_name)
586+
{
530587
function
531588
} else {
532-
overloaded_functions.push(OverloadedFunction {
589+
overloaded_functions.push(OverloadedFunction {
533590
name: function_name.clone(),
534-
variants: Vec::new()
591+
variants: Vec::new(),
535592
});
536593

537594
overloaded_functions.last_mut().unwrap()
@@ -542,7 +599,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
542599
inputs,
543600
output: "bool".to_owned(), // TODO
544601
selector,
545-
selector_hash: selector_hash.encode_hex()
602+
selector_hash: selector_hash.encode_hex(),
546603
})
547604
} else {
548605
functions.push(Function {

0 commit comments

Comments
 (0)