Skip to content

Commit

Permalink
Merge pull request #2 from jam1garner/structopt
Browse files Browse the repository at this point in the history
Refactor to move to structopt and simplify and unify error handling
  • Loading branch information
benhall-7 authored Oct 27, 2019
2 parents a3e4282 + 9c3f38f commit 51cb628
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 188 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ byteorder = "1.3.2"
serde = { version = "1.0.98", features = ["derive"] }
serde_yaml = "0.8"
indexmap = { version = "1.2.0", features = ["serde-1"] }
lazy_static = "1.4.0"
lazy_static = "1.4.0"
structopt = "0.3.3"
19 changes: 6 additions & 13 deletions src/motion_lib/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,13 @@ use std::io::{prelude::*, Cursor, Error};
use std::path::Path;

pub fn open<P: AsRef<Path>>(file: P) -> Result<MList, Error> {
match read(file) {
Ok(x) => disasm::disassemble(&mut Cursor::new(x)),
Err(y) => Err(y),
}
disasm::disassemble(&mut Cursor::new(read(file)?))
}

pub fn save<P: AsRef<Path>>(path: P, mlist: &MList) -> Result<(), Error> {
match File::create(path) {
Ok(mut file) => {
let mut cursor = Cursor::new(Vec::<u8>::new());
asm::assemble(&mut cursor, mlist)?;
file.write_all(&cursor.into_inner())?;
Ok(())
}
Err(y) => Err(y),
}
let mut file = File::create(path)?;
let mut cursor = Cursor::new(Vec::<u8>::new());
asm::assemble(&mut cursor, mlist)?;
file.write_all(&cursor.into_inner())?;
Ok(())
}
36 changes: 36 additions & 0 deletions src/yamlist/args.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use structopt::StructOpt;

#[derive(StructOpt)]
pub struct Args {
#[structopt(subcommand)]
pub mode: Mode,

#[structopt(long, short, global(true))]
pub label: Option<String>,

#[structopt(long, short, global(true))]
pub out: Option<String>,
}

#[derive(StructOpt)]
pub enum Mode {
#[structopt(about = "Convert from motion_list to yaml")]
Disasm {
file: String,
},

#[structopt(about = "Convert from yaml to motion_list")]
Asm {
file: String,
},

Patch {
file: String,
patch: String,
},

Diff {
a: String,
b: String,
},
}
30 changes: 30 additions & 0 deletions src/yamlist/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
pub struct ErrorMessage {
msg: String,
}

pub struct ErrorString(pub &'static str);

impl<E> From<E> for ErrorMessage
where E: std::error::Error
{
fn from(error: E) -> Self {
Self {
msg: format!("{}", error)
}
}
}

impl From<ErrorString> for ErrorMessage
{
fn from(error: ErrorString) -> Self {
Self {
msg: format!("{}", error.0)
}
}
}

impl std::fmt::Display for ErrorMessage {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
write!(fmt, "{}", self.msg)
}
}
214 changes: 40 additions & 174 deletions src/yamlist/main.rs
Original file line number Diff line number Diff line change
@@ -1,203 +1,69 @@
use motion_lib;
use serde_yaml::{from_str, to_string};
use std::borrow::Borrow;
use std::env;
use std::error::Error;
use std::fs::File;
use std::io::prelude::*;

enum Mode {
Disasm {
file: String,
},
Asm {
file: String,
},
Patch {
file: String,
patch: String,
},
Compare {
a: String,
b: String,
},
}

fn main() {
let args: Vec<String> = env::args().collect();
let len = args.len();
let mode: Mode;
let mut labelname = String::default();
let mut outname = String::default();
mod args;
use args::{Args, Mode};
use structopt::StructOpt;

if len <= 1 {
print_help_text();
return;
}

let mut arg_index: usize;
match args[1].as_ref() {
"-h" => {
print_help_text();
return;
}
"-d" => {
if len > 2 {
mode = Mode::Disasm {
file: String::from(&args[2])
};
} else {
println!("missing 'FILE' arg for disassembly");
return;
}
arg_index = 3;
}
"-a" => {
if len > 2 {
mode = Mode::Asm {
file: String::from(&args[2])
}
} else {
println!("missing 'FILE' arg for assembly");
return;
}
arg_index = 3;
}
"-p" => {
if len > 3 {
mode = Mode::Patch {
file: String::from(&args[2]),
patch: String::from(&args[3])
}
} else {
println!("missing 'FILE' or 'PATCH' arg for patching");
return;
}
arg_index = 4;
}
"-c" => {
if len > 3 {
mode = Mode::Compare {
a: String::from(&args[2]),
b: String::from(&args[3])
}
} else {
println!("missing 'A' or 'B' arg for comparison");
return;
}
arg_index = 4;
}
_ => {
println!("Unrecognized mode: '{}'", &args[1]);
return;
},
}
mod error;
use error::{ErrorMessage, ErrorString};

while arg_index < len {
match args[arg_index].as_ref() {
"-l" => {
arg_index += 1;
if arg_index < len {
labelname = String::from(&args[arg_index]);
} else {
println!("missing 'FILE' arg for labels");
}
}
"-o" => {
arg_index += 1;
if arg_index < len {
outname = String::from(&args[arg_index]);
} else {
println!("missing 'OUTNAME' arg for output name");
}
},
_ => {
type Result<T> = std::result::Result<T, ErrorMessage>;

}
}
arg_index += 1;
}
fn main() {
let args = Args::from_args();

if !labelname.is_empty() {
if let Err(e) = motion_lib::hash40::load_labels(&labelname) {
if let Some(ref label_path) = args.label {
if let Err(e) = motion_lib::hash40::load_labels(label_path) {
println!("Error loading labels: {}", e);
return;
}
}

match mode {
Mode::Disasm {file} => {
let o = if !outname.is_empty() {
&outname
} else {
"out.yml"
};

match convert_to_yaml(&file, o) {
Ok(_) => {}
Err(y) => {
let e: &dyn Error = y.borrow();
println!("ERROR: {}", e);
}
}
if let Err(y) = match &args.mode {
Mode::Disasm {file, ..} => {
convert_to_yaml(&file, &args.out.as_ref().map_or("out.yml", String::as_str))
}
Mode::Asm {file} => {
let o = if !outname.is_empty() {
&outname
} else {
"out.bin"
};

match convert_to_bin(&file, o) {
Ok(_) => {}
Err(y) => {
let e: &dyn Error = y.borrow();
println!("ERROR: {}", e);
}
}
Mode::Asm {file, ..} => {
convert_to_bin(&file, &args.out.as_ref().map_or("out.bin", String::as_str))
}
Mode::Patch {..} => {
unimplemented!()
patch_motion_bin()
}
Mode::Compare {..} => {
unimplemented!()
Mode::Diff {..} => {
diff_files()
}
} {
println!("ERROR: {}", y);
}
}

fn print_help_text() {
println!("Args: [MODE] [OTHER]");
println!("MODE:");
println!(" -h (print help)");
println!(" -d (disassemble) <FILE>");
println!(" -a (assemble) <FILE>");
println!(" -p (patch) <FILE> <PATCH>");
println!(" -c (compare) <A> <B>");
println!("OTHER:");
println!(" -l (label) <FILE>");
println!(" -o (out) <OUTNAME>");
// TODO: args/implementation
fn patch_motion_bin() -> Result<()> {
Err(ErrorString("Patching not supported"))?
}

fn convert_to_yaml(i: &str, o: &str) -> Result<(), Box<dyn Error>> {
match motion_lib::open(i) {
Ok(x) => {
let mut f = File::create(o)?;
let pretty = to_string(&x)?;
f.write_all(pretty.as_bytes())?;
Ok(())
}
Err(y) => Err(Box::new(y)),
}
// TODO: args/implementation
fn diff_files() -> Result<()> {
Err(ErrorString("Diffing not supported"))?
}

fn convert_to_bin(in_path: &str, out_path: &str) -> Result<(), Box<dyn Error>> {
fn convert_to_yaml(in_path: &str, out_path: &str) -> Result<()> {
let x = motion_lib::open(in_path)?;
let mut f = File::create(out_path)?;
let pretty = to_string(&x)?;
f.write_all(pretty.as_bytes())?;
Ok(())
}

fn convert_to_bin(in_path: &str, out_path: &str) -> Result<()> {
let mut file = File::open(in_path)?;
let mut contents: String = String::default();
file.read_to_string(&mut contents)?;
match from_str(&contents) {
Ok(mlist) => match motion_lib::save(out_path, &mlist) {
Ok(_) => Ok(()),
Err(y) => Err(Box::new(y)),
},
Err(y) => Err(Box::new(y)),
}

let mlist = from_str(&contents)?;
motion_lib::save(out_path, &mlist)?;
Ok(())
}

0 comments on commit 51cb628

Please sign in to comment.