From 0400b5f12af0df011283e9cf94996b40f8d324fa Mon Sep 17 00:00:00 2001 From: jam1garner Date: Tue, 22 Oct 2019 19:38:04 -0400 Subject: [PATCH 1/4] Begin move from manual arg parsing to structopt --- Cargo.toml | 3 +- src/yamlist/args.rs | 36 +++++++++++ src/yamlist/main.rs | 149 ++++---------------------------------------- 3 files changed, 49 insertions(+), 139 deletions(-) create mode 100644 src/yamlist/args.rs diff --git a/Cargo.toml b/Cargo.toml index bf67b74..1fb3e63 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" \ No newline at end of file +lazy_static = "1.4.0" +structopt = "0.3.3" diff --git a/src/yamlist/args.rs b/src/yamlist/args.rs new file mode 100644 index 0000000..473d10c --- /dev/null +++ b/src/yamlist/args.rs @@ -0,0 +1,36 @@ +use structopt::StructOpt; + +#[derive(StructOpt)] +pub struct Args { + #[structopt(subcommand)] + pub mode: Mode, + + #[structopt(long, short)] + pub label: Option, + + #[structopt(long, short)] + pub out: Option, +} + +#[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, + }, +} diff --git a/src/yamlist/main.rs b/src/yamlist/main.rs index 07489c3..471a566 100644 --- a/src/yamlist/main.rs +++ b/src/yamlist/main.rs @@ -1,138 +1,28 @@ 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, - }, -} +mod args; +use args::{Args, Mode}; +use structopt::StructOpt; fn main() { - let args: Vec = env::args().collect(); - let len = args.len(); - let mode: Mode; - let mut labelname = String::default(); - let mut outname = String::default(); - - 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; - }, - } - - 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"); - } - }, - _ => { + let args = Args::from_args(); - } - } - arg_index += 1; - } - - if !labelname.is_empty() { + if let Some(labelname) = args.label { if let Err(e) = motion_lib::hash40::load_labels(&labelname) { println!("Error loading labels: {}", e); } } - match mode { + match args.mode { Mode::Disasm {file} => { - let o = if !outname.is_empty() { - &outname - } else { - "out.yml" - }; + let o = args.out.unwrap_or("out.yml".into()); - match convert_to_yaml(&file, o) { + match convert_to_yaml(&file, &o) { Ok(_) => {} Err(y) => { let e: &dyn Error = y.borrow(); @@ -141,13 +31,9 @@ fn main() { } } Mode::Asm {file} => { - let o = if !outname.is_empty() { - &outname - } else { - "out.bin" - }; + let o = args.out.unwrap_or("out.yml".into()); - match convert_to_bin(&file, o) { + match convert_to_bin(&file, &o) { Ok(_) => {} Err(y) => { let e: &dyn Error = y.borrow(); @@ -158,25 +44,12 @@ fn main() { Mode::Patch {..} => { unimplemented!() } - Mode::Compare {..} => { + Mode::Diff {..} => { unimplemented!() } } } -fn print_help_text() { - println!("Args: [MODE] [OTHER]"); - println!("MODE:"); - println!(" -h (print help)"); - println!(" -d (disassemble) "); - println!(" -a (assemble) "); - println!(" -p (patch) "); - println!(" -c (compare) "); - println!("OTHER:"); - println!(" -l (label) "); - println!(" -o (out) "); -} - fn convert_to_yaml(i: &str, o: &str) -> Result<(), Box> { match motion_lib::open(i) { Ok(x) => { From c7718da42b4d3723a87a393007298f05c581e4bd Mon Sep 17 00:00:00 2001 From: jam1garner Date: Wed, 23 Oct 2019 18:20:58 -0400 Subject: [PATCH 2/4] Refactor to use structopt --- src/motion_lib/lib.rs | 19 ++++-------- src/yamlist/args.rs | 44 ++++++++++++++++++++++++++++ src/yamlist/error.rs | 19 ++++++++++++ src/yamlist/main.rs | 68 ++++++++++++++++--------------------------- 4 files changed, 94 insertions(+), 56 deletions(-) create mode 100644 src/yamlist/error.rs diff --git a/src/motion_lib/lib.rs b/src/motion_lib/lib.rs index 4cfbcf9..6962d8f 100644 --- a/src/motion_lib/lib.rs +++ b/src/motion_lib/lib.rs @@ -13,20 +13,13 @@ use std::io::{prelude::*, Cursor, Error}; use std::path::Path; pub fn open>(file: P) -> Result { - 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>(path: P, mlist: &MList) -> Result<(), Error> { - match File::create(path) { - Ok(mut file) => { - let mut cursor = Cursor::new(Vec::::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::::new()); + asm::assemble(&mut cursor, mlist)?; + file.write_all(&cursor.into_inner())?; + Ok(()) } diff --git a/src/yamlist/args.rs b/src/yamlist/args.rs index 473d10c..d2f409c 100644 --- a/src/yamlist/args.rs +++ b/src/yamlist/args.rs @@ -17,11 +17,23 @@ pub enum Mode { #[structopt(about = "Convert from motion_list to yaml")] Disasm { file: String, + + #[structopt(long, short)] + label: Option, + + #[structopt(long, short)] + out: Option, }, #[structopt(about = "Convert from yaml to motion_list")] Asm { file: String, + + #[structopt(long, short)] + label: Option, + + #[structopt(long, short)] + out: Option, }, Patch { @@ -34,3 +46,35 @@ pub enum Mode { b: String, }, } + +impl Args { + pub fn get_label<'a>(&'a self) -> Option<&'a String> { + if self.label.is_some() { + self.label.as_ref() + } else { + match &self.mode { + Mode::Asm {label, ..} | Mode::Disasm {label, ..} => { + label.as_ref() + } + _ => None + } + } + } + + pub fn get_outfile<'a>(&'a self) -> &'a str { + self.out + .as_ref() + .map_or( + match &self.mode { + Mode::Asm {out, ..} => { + out.as_ref().map_or("out.bin", String::as_str) + } + Mode::Disasm {out, ..} => { + out.as_ref().map_or("out.yml", String::as_str) + } + _ => "out.bin" + }, + String::as_str + ) + } +} diff --git a/src/yamlist/error.rs b/src/yamlist/error.rs new file mode 100644 index 0000000..52beec6 --- /dev/null +++ b/src/yamlist/error.rs @@ -0,0 +1,19 @@ +pub struct ErrorMessage { + msg: String, +} + +impl From for ErrorMessage + where E: std::error::Error +{ + fn from(error: E) -> Self { + Self { + msg: format!("{}", error) + } + } +} + +impl std::fmt::Display for ErrorMessage { + fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { + write!(fmt, "{}", self.msg) + } +} diff --git a/src/yamlist/main.rs b/src/yamlist/main.rs index 471a566..cd0aa08 100644 --- a/src/yamlist/main.rs +++ b/src/yamlist/main.rs @@ -1,7 +1,5 @@ use motion_lib; use serde_yaml::{from_str, to_string}; -use std::borrow::Borrow; -use std::error::Error; use std::fs::File; use std::io::prelude::*; @@ -9,37 +7,26 @@ mod args; use args::{Args, Mode}; use structopt::StructOpt; +mod error; +use error::ErrorMessage; + +type Result = std::result::Result; + fn main() { let args = Args::from_args(); - if let Some(labelname) = args.label { - if let Err(e) = motion_lib::hash40::load_labels(&labelname) { + if let Some(ref label_path) = args.get_label() { + if let Err(e) = motion_lib::hash40::load_labels(label_path) { println!("Error loading labels: {}", e); } } - match args.mode { - Mode::Disasm {file} => { - let o = args.out.unwrap_or("out.yml".into()); - - 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.get_outfile()) } - Mode::Asm {file} => { - let o = args.out.unwrap_or("out.yml".into()); - - 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.get_outfile()) } Mode::Patch {..} => { unimplemented!() @@ -47,30 +34,25 @@ fn main() { Mode::Diff {..} => { unimplemented!() } + } { + println!("ERROR: {}", y); } } -fn convert_to_yaml(i: &str, o: &str) -> Result<(), Box> { - 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)), - } +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<(), Box> { +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(()) } From 2b8560667a8046f1c6925b54163d775ab5880c72 Mon Sep 17 00:00:00 2001 From: jam1garner Date: Sun, 27 Oct 2019 15:36:25 -0400 Subject: [PATCH 3/4] Clean up error printing for unimplemented features --- src/yamlist/error.rs | 11 +++++++++++ src/yamlist/main.rs | 16 +++++++++++++--- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/yamlist/error.rs b/src/yamlist/error.rs index 52beec6..64dfd70 100644 --- a/src/yamlist/error.rs +++ b/src/yamlist/error.rs @@ -2,6 +2,8 @@ pub struct ErrorMessage { msg: String, } +pub struct ErrorString(pub &'static str); + impl From for ErrorMessage where E: std::error::Error { @@ -12,6 +14,15 @@ impl From for ErrorMessage } } +impl From 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) diff --git a/src/yamlist/main.rs b/src/yamlist/main.rs index cd0aa08..6033ae1 100644 --- a/src/yamlist/main.rs +++ b/src/yamlist/main.rs @@ -8,7 +8,7 @@ use args::{Args, Mode}; use structopt::StructOpt; mod error; -use error::ErrorMessage; +use error::{ErrorMessage, ErrorString}; type Result = std::result::Result; @@ -29,16 +29,26 @@ fn main() { convert_to_bin(&file, &args.get_outfile()) } Mode::Patch {..} => { - unimplemented!() + patch_motion_bin() } Mode::Diff {..} => { - unimplemented!() + diff_files() } } { println!("ERROR: {}", y); } } +// TODO: args/implementation +fn patch_motion_bin() -> Result<()> { + Err(ErrorString("Patching not supported"))? +} + +// TODO: args/implementation +fn diff_files() -> Result<()> { + Err(ErrorString("Diffing not supported"))? +} + 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)?; From 9c3f38f7fb6580e3e8f9557ff0a514c142b8eb90 Mon Sep 17 00:00:00 2001 From: jam1garner Date: Sun, 27 Oct 2019 16:16:27 -0400 Subject: [PATCH 4/4] Add proper global flags in subcommand functionality --- src/yamlist/args.rs | 48 ++------------------------------------------- src/yamlist/main.rs | 7 ++++--- 2 files changed, 6 insertions(+), 49 deletions(-) diff --git a/src/yamlist/args.rs b/src/yamlist/args.rs index d2f409c..2c5e92a 100644 --- a/src/yamlist/args.rs +++ b/src/yamlist/args.rs @@ -5,10 +5,10 @@ pub struct Args { #[structopt(subcommand)] pub mode: Mode, - #[structopt(long, short)] + #[structopt(long, short, global(true))] pub label: Option, - #[structopt(long, short)] + #[structopt(long, short, global(true))] pub out: Option, } @@ -17,23 +17,11 @@ pub enum Mode { #[structopt(about = "Convert from motion_list to yaml")] Disasm { file: String, - - #[structopt(long, short)] - label: Option, - - #[structopt(long, short)] - out: Option, }, #[structopt(about = "Convert from yaml to motion_list")] Asm { file: String, - - #[structopt(long, short)] - label: Option, - - #[structopt(long, short)] - out: Option, }, Patch { @@ -46,35 +34,3 @@ pub enum Mode { b: String, }, } - -impl Args { - pub fn get_label<'a>(&'a self) -> Option<&'a String> { - if self.label.is_some() { - self.label.as_ref() - } else { - match &self.mode { - Mode::Asm {label, ..} | Mode::Disasm {label, ..} => { - label.as_ref() - } - _ => None - } - } - } - - pub fn get_outfile<'a>(&'a self) -> &'a str { - self.out - .as_ref() - .map_or( - match &self.mode { - Mode::Asm {out, ..} => { - out.as_ref().map_or("out.bin", String::as_str) - } - Mode::Disasm {out, ..} => { - out.as_ref().map_or("out.yml", String::as_str) - } - _ => "out.bin" - }, - String::as_str - ) - } -} diff --git a/src/yamlist/main.rs b/src/yamlist/main.rs index 6033ae1..abfcd8f 100644 --- a/src/yamlist/main.rs +++ b/src/yamlist/main.rs @@ -15,18 +15,19 @@ type Result = std::result::Result; fn main() { let args = Args::from_args(); - if let Some(ref label_path) = args.get_label() { + 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; } } if let Err(y) = match &args.mode { Mode::Disasm {file, ..} => { - convert_to_yaml(&file, &args.get_outfile()) + convert_to_yaml(&file, &args.out.as_ref().map_or("out.yml", String::as_str)) } Mode::Asm {file, ..} => { - convert_to_bin(&file, &args.get_outfile()) + convert_to_bin(&file, &args.out.as_ref().map_or("out.bin", String::as_str)) } Mode::Patch {..} => { patch_motion_bin()