|
|
@@ -1,42 +1,55 @@
|
|
|
-use std::{ffi::OsString, io::Write};
|
|
|
+use std::io::Write;
|
|
|
|
|
|
+use anyhow::{Context, anyhow};
|
|
|
use clap::Parser;
|
|
|
use huffman::{cli, hufftree, storage};
|
|
|
|
|
|
-fn main() -> Result<(), std::io::Error> {
|
|
|
+fn main() -> Result<(), anyhow::Error> {
|
|
|
let args = cli::Args::parse();
|
|
|
|
|
|
let inputf = args.input_file;
|
|
|
let outputf = args.output_file;
|
|
|
let mode = args.mode;
|
|
|
|
|
|
+ if !inputf.exists() {
|
|
|
+ return Err(anyhow!("Input file did not exist."));
|
|
|
+ }
|
|
|
+
|
|
|
let outputf = match outputf {
|
|
|
Some(name) => name,
|
|
|
None => match mode {
|
|
|
cli::Mode::X => {
|
|
|
- let mut temp = inputf
|
|
|
- .clone()
|
|
|
- .into_string()
|
|
|
- .expect("Not a valid input file name.");
|
|
|
- if temp.ends_with(".z") {
|
|
|
- temp.pop();
|
|
|
- temp.pop();
|
|
|
+ if let Some(ext) = inputf.extension()
|
|
|
+ && ext.eq("z")
|
|
|
+ {
|
|
|
+ inputf.with_extension("")
|
|
|
} else {
|
|
|
- temp.push_str(".unhuffed");
|
|
|
+ inputf.with_extension("unhuffed")
|
|
|
}
|
|
|
- OsString::from(temp)
|
|
|
- }
|
|
|
- cli::Mode::C => {
|
|
|
- let mut temp = inputf.clone();
|
|
|
- temp.push(".z");
|
|
|
- temp
|
|
|
}
|
|
|
+ cli::Mode::C => match inputf.extension() {
|
|
|
+ // Check if we have an extension
|
|
|
+ Some(ext) => {
|
|
|
+ // If so we retrieve it and then add to it a ".z"
|
|
|
+ let ext = ext
|
|
|
+ .to_str()
|
|
|
+ .ok_or(anyhow!("Input file path was not valid unicode."))?;
|
|
|
+ let new_extension = ext.to_string() + ".z";
|
|
|
+
|
|
|
+ inputf.with_extension(new_extension)
|
|
|
+ }
|
|
|
+ // Otherwise just use the native syntax for add '.z'
|
|
|
+ None => inputf.with_extension(".z"),
|
|
|
+ },
|
|
|
},
|
|
|
};
|
|
|
|
|
|
let working_directory = std::path::Path::new(".");
|
|
|
let inputf = working_directory.join(inputf);
|
|
|
- let in_size = inputf.metadata().unwrap().len();
|
|
|
+ let in_size = inputf
|
|
|
+ .metadata()
|
|
|
+ .context("Could not get the input file's metadata")?
|
|
|
+ .len();
|
|
|
|
|
|
let outputf = working_directory.join(outputf);
|
|
|
let mut outputf = std::fs::File::create(outputf)?;
|
|
|
@@ -49,8 +62,13 @@ fn main() -> Result<(), std::io::Error> {
|
|
|
let decoded_text = huffman::storage::read_tree_and_text(&mut &inputf[..]);
|
|
|
println!("Decoded!");
|
|
|
|
|
|
- outputf.write_all(decoded_text.as_bytes()).unwrap();
|
|
|
- let out_size = outputf.metadata().unwrap().len();
|
|
|
+ outputf
|
|
|
+ .write_all(decoded_text.as_bytes())
|
|
|
+ .context("Could not write decoded text to output file.")?;
|
|
|
+ let out_size = outputf
|
|
|
+ .metadata()
|
|
|
+ .context("Could not get the input file's metadata")?
|
|
|
+ .len();
|
|
|
println!("Stored: {} bytes.", out_size);
|
|
|
println!(
|
|
|
"Compression Ratio: {:.2}.",
|
|
|
@@ -59,7 +77,8 @@ fn main() -> Result<(), std::io::Error> {
|
|
|
}
|
|
|
|
|
|
cli::Mode::C => {
|
|
|
- let inputf = std::fs::read_to_string(inputf)?;
|
|
|
+ let inputf =
|
|
|
+ std::fs::read_to_string(inputf).context("Could not read input file to string.")?;
|
|
|
println!("Read: {} bytes.", in_size);
|
|
|
let char_f = huffman::hufftree::base::get_char_frequencies(&inputf);
|
|
|
|
|
|
@@ -68,7 +87,10 @@ fn main() -> Result<(), std::io::Error> {
|
|
|
|
|
|
storage::store_tree_and_text(canonical_tree, &mut outputf, &inputf)
|
|
|
.expect("Could not store the tree and text.");
|
|
|
- let out_size = outputf.metadata().unwrap().len();
|
|
|
+ let out_size = outputf
|
|
|
+ .metadata()
|
|
|
+ .context("Could not get the input file's metadata")?
|
|
|
+ .len();
|
|
|
println!("Stored: {} bytes.", out_size);
|
|
|
println!(
|
|
|
"Compression Ratio: {:.2}.",
|