use chrono::prelude::Utc;
use clap::Parser;
use hhh::configure_logging;
use hhh::directive_def::directives_help;
use hhh::directive_def::parse_and_do_directive;
use hhh::directive_def::set_groups;
use hhh::get_config_file;
use hhh::options::HhhArgs;
use hhh::read_configuration::read_configuration_file;
use hhh::read_hexdump;
use hhh::write_hexdump;
use log::debug;
use log::error;
use std::collections::BTreeMap;
use std::fs::File;
use std::io::stdout;
use std::io::Write;
use std::process::ExitCode;
use trivet::Tools;
fn main() -> ExitCode {
configure_logging();
let mut args = HhhArgs::parse();
debug!("Command line: {:?}", args);
if !args.no_configuration_file {
match get_config_file() {
Err(error) => {
error!("{}", error);
return ExitCode::FAILURE;
}
Ok(path) => {
debug!("Configuration file: {:?}", &path);
match read_configuration_file(&path, &mut args) {
Ok(_) => {}
Err(error) => {
error!("{}", error);
return ExitCode::FAILURE;
}
}
}
}
}
if args.groups_per_line == 0 {
set_groups(&mut args);
}
args.bytes_per_group = 1.max(args.bytes_per_group);
if args.list_directives {
directives_help();
return ExitCode::SUCCESS;
}
let directives = std::mem::take(&mut args.directives);
for directive in directives {
match parse_and_do_directive(&directive, &mut args) {
Ok(None) => {}
Ok(Some(msg)) => {
error!("ERROR: {}", msg);
return ExitCode::FAILURE;
}
Err(msg) => {
error!("ERROR: {}", msg);
return ExitCode::FAILURE;
}
}
}
let sink = match args.output {
Some(ref path) => match File::create(path) {
Err(msg) => {
error!("ERROR: Unable to create output file: {}", msg);
return ExitCode::FAILURE;
}
Ok(file) => Box::new(file),
},
None => Box::new(stdout()) as Box<dyn Write>,
};
if args.parse {
if let Err(msg) = read_hexdump(args, sink) {
error!("ERROR: Failed to parse hexdump: {}", msg);
return ExitCode::FAILURE;
};
ExitCode::SUCCESS
} else {
let mut map = BTreeMap::new();
let tools = Tools::new();
if args.meta {
let cmd = std::env::args()
.skip(1)
.map(|arg| format!("\"{}\"", tools.encode_string(&arg)))
.collect::<Vec<_>>()
.join(" ");
map.insert("Command-Line".to_string(), cmd);
map.insert("UTC".to_string(), Utc::now().to_string());
for (key, value) in &args.set_meta {
if value.is_empty() {
map.remove(key);
} else {
map.insert(key.to_owned(), value.to_owned());
}
}
}
if let Err(msg) = write_hexdump(args, map, sink) {
error!("ERROR: Failed to generate hexdump: {}", msg);
return ExitCode::FAILURE;
};
ExitCode::SUCCESS
}
}