use crate::exit_with_error; use std::{borrow::Cow, path::PathBuf}; #[derive(Debug)] pub struct Args { pub rom_path: PathBuf, pub is_cli: bool, pub zoom: Option, pub symbols_path: Option, pub rom_args: Vec, } impl Args { pub fn parse() -> Self { let mut args = std::env::args(); let _program = args.next().unwrap(); let mut rom_path = None; let mut is_cli = false; let mut zoom = None; let mut symbols_path = None; let mut rom_args = Vec::new(); let mut horizon_encountered = false; while let Some(arg) = args.next() { if horizon_encountered { rom_args.push(arg); continue; } if arg == "--" { horizon_encountered = true; continue; } if arg.starts_with("--") { match &arg[2..] { "cli" => { is_cli = true; } "zoom" => { let value = args .next() .unwrap_or_else(|| { exit_with_error!("no value provided for argument `{arg}`"); }) .parse::() .unwrap_or_else(|inner| { exit_with_error!( "invalid value provided for argument `{arg}`: {inner}" ); }); zoom.replace(value); } "symbols" => { let path = args.next().unwrap_or_else(|| { exit_with_error!("no value provided for argument `{arg}`"); }); symbols_path.replace(PathBuf::from(path)); } "port" => { args.next().unwrap_or_else(|| { exit_with_error!("no value provided for argument `{arg}`"); }); } _ => { exit_with_error!("invalid argument `{arg}`"); } } } else if arg.starts_with("-") { let mut opts = arg[1..].chars(); while let Some(opt) = opts.next() { match opt { 'c' => { is_cli = true; } 'z' => { let string: Cow = if opts.as_str().is_empty() { args.next() .unwrap_or_else(|| { exit_with_error!("no value provided for argument `-{opt}`"); }) .into() } else { opts.as_str().into() }; let value = string.parse::().unwrap_or_else(|inner| { exit_with_error!( "invalid value provided for argument `-{opt}`: {inner}" ); }); zoom.replace(value); break; } 's' => { let string: Cow = if opts.as_str().is_empty() { args.next() .unwrap_or_else(|| { exit_with_error!("no value provided for argument `-{opt}`"); }) .into() } else { opts.as_str().into() }; symbols_path.replace(PathBuf::from(string.to_string())); break; } opt => { exit_with_error!("invalid option {opt}"); } } } } else { if rom_path.is_none() { rom_path.replace(PathBuf::from(arg)); continue; } exit_with_error!("unexpected argument `{arg}`"); } } Self { rom_path: rom_path.unwrap_or_else(|| exit_with_error!("ROM path not provided")), is_cli, zoom, symbols_path, rom_args, } } }