use clap::{Arg, Command};
use std::io::{BufRead, Read, Write};
use stream_vbyte::{decode::decode, encode::encode, scalar::Scalar};
fn main() {
let matches = Command::new("stream-vbyte cli")
.subcommand(Command::new("enc").about("Encode numbers"))
.subcommand(
Command::new("dec").about("Decode numbers").arg(
Arg::new("count")
.help("count of numbers in encoded input")
.short('c')
.long("count")
.required(true),
),
)
.get_matches();
match matches.subcommand_name() {
Some("enc") => run_encode(),
Some("dec") => {
let count: usize = matches
.subcommand_matches("dec")
.unwrap()
.get_one::<String>("count")
.unwrap()
.parse()
.expect("count must be an int");
run_decode(count);
}
_ => println!("Invalid subcommand"),
}
}
fn run_encode() {
let stdin = std::io::stdin();
let stdin_handle = stdin.lock();
let nums: Vec<u32> = stdin_handle
.lines()
.map(|l| l.expect("Should be able to read stdin"))
.map(|s| s.parse().expect("Each line must be a u32"))
.collect();
let mut encoded = Vec::new();
encoded.resize(nums.len() * 5, 0);
let encoded_len = encode::<Scalar>(&nums, &mut encoded);
let stdout = std::io::stdout();
let mut stdout_handle = stdout.lock();
stdout_handle
.write_all(&encoded[0..encoded_len])
.expect("Should be able to write to stdout");
eprintln!("Encoded {} numbers", nums.len());
}
fn run_decode(count: usize) {
let stdin = std::io::stdin();
let mut stdin_handle = stdin.lock();
let mut encoded = Vec::new();
stdin_handle
.read_to_end(&mut encoded)
.expect("Should be able to read stdin");
let mut decoded = Vec::new();
decoded.resize(count, 0);
decode::<Scalar>(&encoded, count, &mut decoded);
for d in &decoded {
println!("{}", d);
}
eprintln!("Decoded {} numbers", decoded.len());
}