yglnk/crates/yglnk-ls/src/main.rs
2023-01-09 20:07:18 +01:00

109 lines
3 KiB
Rust

use clap::Subcommand;
use clap_num::maybe_hex;
use std::path::PathBuf;
#[derive(clap::Parser)]
struct Cli {
/// the file to operate on
#[arg(short, long)]
file: PathBuf,
/// section location
#[arg(short, long, default_value_t = 1, value_parser = maybe_hex::<u32>)]
location: u32,
#[command(subcommand)]
command: Command,
}
#[derive(Subcommand)]
enum Command {
/// list linear table
Linear,
/// list hash table
Hash,
/// resolve a key via hash table
HashLookup { key: String },
/// list 2D "hilbert curve" table
X2dhc,
}
fn typ_to_txt(typ: u32) -> String {
use yglnk_core::IntEnum;
match yglnk_core::Type::from_int(typ) {
Ok(x) => format!("{:?}", x),
Err(_) => format!("{:08x}", typ),
}
}
fn name_to_txt(name: &[u8]) -> String {
if let Ok(name) = core::str::from_utf8(name) {
format!("{:?}", name)
} else {
"0x".chars()
.chain(
name.iter()
.flat_map(|i| format!("{:02x}", i).chars().collect::<Vec<_>>()),
)
.collect()
}
}
fn main() {
let cli = <Cli as clap::Parser>::parse();
let fh = std::fs::File::open(&cli.file).expect("unable to open specified file");
let data = unsafe {
memmap2::MmapOptions::new()
.map(&fh)
.expect("unable to mmap specified file")
};
let data = &data[..];
match &cli.command {
Command::Linear => {
let ltr = yglnk_core::LinearTableRef::parse(data, cli.location)
.expect("unable to parse table header");
println!("location\tmeta\t\tname\t\ttyp\t\trest");
for i in ltr {
println!(
"{:08x}\t{:08x}\t{}\t{}\t{}",
i.location,
i.meta,
name_to_txt(i.name),
typ_to_txt(i.typ),
name_to_txt(i.rest),
);
}
}
Command::Hash => {
let ht = yglnk_core::hash_table::Ref::parse(data, cli.location)
.expect("unable to parse table header");
println!("hash\t\tname\t\ttyp\trest");
for (hash, name, value) in ht.iter() {
println!(
"{:016x}\t{}\t{}\t{}",
hash,
name_to_txt(name),
typ_to_txt(value.typ),
name_to_txt(value.rest),
);
}
}
Command::HashLookup { key } => {
let ht = yglnk_core::hash_table::Ref::parse(data, cli.location)
.expect("unable to parse table header");
match ht.lookup(key.as_bytes()) {
None => println!("(none)"),
Some(value) => {
println!("typ={} {}", typ_to_txt(value.typ), name_to_txt(value.rest),)
}
}
}
Command::X2dhc => unimplemented!(),
}
}