use clap::{arg, Arg, Command};
use std::path::PathBuf;
use std::str::FromStr;
use ledger_kv::{LedgerKV, EntryLabel};
struct ParsedArgs {
list: bool,
add: Option<(String, String)>,
delete: Option<String>,
directory: Option<String>,
}
fn parse_args() -> ParsedArgs {
let matches = Command::new("LedgerKV CLI")
.about("LedgerKV CLI")
.arg(arg!(--list "List entries").required(false))
.arg(
Arg::new("add")
.long("add")
.help("Add key-value pair")
.num_args(2),
)
.arg(arg!(--delete <KEY> "Delete key").required(false))
.arg(
arg!(--directory <VALUE> "Specify directory to store ledger")
.required(false)
.default_value("."),
)
.get_matches();
let list = *matches.get_one::<bool>("list").unwrap_or(&false);
let add = matches.get_many::<String>("add").map(|mut vals| {
(
vals.next().unwrap().to_string(),
vals.next().unwrap().to_string(),
)
});
let delete = matches.get_one::<String>("delete").map(|s| s.to_string());
let directory = matches
.get_one::<String>("directory")
.map(|s| s.to_string());
ParsedArgs {
list,
add,
delete,
directory,
}
}
fn main() -> anyhow::Result<()> {
let args = parse_args();
let dir = args.directory.as_ref().expect("directory not provided");
let data_dir = PathBuf::from_str(dir)
.map_err(|e| format!("Failed to parse directory path {}: {}", dir, e))
.unwrap();
let file_name = "store.bin";
let mut ledger_kv = LedgerKV::new(data_dir, file_name);
if args.list {
println!("Listing entries:");
for entry in ledger_kv.iter(None) {
println!(
"Key: {}, Value: {}",
String::from_utf8_lossy(&entry.key),
String::from_utf8_lossy(&entry.value)
);
}
}
if let Some((key, value)) = args.add {
ledger_kv.upsert(
EntryLabel::Unspecified,
key.as_bytes().to_vec(),
value.as_bytes().to_vec(),
)?;
println!("Add entry with KEY: {}, VALUE: {}", key, value);
}
if let Some(key) = args.delete {
ledger_kv.delete(EntryLabel::Unspecified, key.as_bytes().to_vec())?;
println!("Delete entry with KEY: {}", key);
}
Ok(())
}