#[macro_use]
extern crate clap;
use std::fs::OpenOptions;
use std::io::{self, Read, Write};
use anyhow::{Context, Result};
use memmap::MmapMut;
use uclcli::{compress, compress_into_buffer, minimum_compression_buffer_size, ucl_init};
fn main() -> Result<()> {
let matches = clap_app!(ucl =>
(version: "0.1")
(author: "Kjell Braden <kjell.braden@bmw.de>")
(about: "libucl (NRV) compressor")
(@arg INPUT: -i --input [FILE] "Sets the input file to use [defaults to stdin]")
(@arg OUTPUT: -o --output [FILE] "Sets the output file to use [defaults to stdout]")
)
.get_matches();
ucl_init();
let mut input: Box<dyn Read> = match matches.value_of("INPUT") {
Some(path) => Box::new(
OpenOptions::new()
.read(true)
.open(&path)
.context("could not open input file")?,
),
None => Box::new(io::stdin()),
};
let mut inbuffer = Vec::new();
input.read_to_end(&mut inbuffer)?;
let out_size = minimum_compression_buffer_size(inbuffer.len());
let output_filename = matches.value_of("OUTPUT");
match output_filename {
Some(path) => {
let file = OpenOptions::new()
.read(true)
.write(true)
.create(true)
.open(&path)
.context("could not create output file")?;
file.set_len(out_size as u64)
.context("could not resize output file")?;
let numbytes = unsafe {
let mut mmap = MmapMut::map_mut(&file).context("failed to map output file")?;
let nb =
compress_into_buffer(&inbuffer, &mut mmap).context("decompression failed")?;
mmap.flush().context("failed to write output")?;
nb
};
file.set_len(numbytes.into())
.context("failed to truncate output file")?;
}
None => {
let dst = compress(&inbuffer).context("decompression failed")?;
io::stdout().write_all(&dst)?;
}
}
Ok(())
}