diff --git a/src/cli.rs b/src/cli.rs index f8d5c3e..5be83bf 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -4,24 +4,24 @@ use clap::{Arg, Values}; use colored::Colorize; use crate::error; -use crate::extensions::CompressionExtension; +use crate::extensions::CompressionFormat; use crate::file::File; #[derive(PartialEq, Eq, Debug)] -pub enum CommandType { +pub enum CommandKind { Compression( // Files to be compressed Vec, ), Decompression( // Files to be decompressed and their extensions - Vec<(PathBuf, CompressionExtension)>, + Vec<(PathBuf, CompressionFormat)>, ), } #[derive(PartialEq, Eq, Debug)] pub struct Command { - pub command_type: CommandType, + pub kind: CommandKind, pub output: Option, } @@ -66,7 +66,7 @@ impl TryFrom> for Command { fn try_from(matches: clap::ArgMatches<'static>) -> error::OuchResult { let process_decompressible_input = |input_files: Values| { let input_files = - input_files.map(|filename| (filename, CompressionExtension::try_from(filename))); + input_files.map(|filename| (filename, CompressionFormat::try_from(filename))); for file in input_files.clone() { if let (file, Err(_)) = file { @@ -91,7 +91,7 @@ impl TryFrom> for Command { if output_was_supplied { let output_file = matches.value_of("output").unwrap(); // Safe unwrap since we've established that output was supplied - let output_file_extension = CompressionExtension::try_from(output_file); + let output_file_extension = CompressionFormat::try_from(output_file); let output_is_compressible = output_file_extension.is_ok(); if output_is_compressible { println!( @@ -103,7 +103,7 @@ impl TryFrom> for Command { let input_files = input_files.map(PathBuf::from).collect(); return Ok(Command { - command_type: CommandType::Compression(input_files), + kind: CommandKind::Compression(input_files), output: Some(File::WithExtension(( output_file.into(), output_file_extension.unwrap(), @@ -120,7 +120,7 @@ impl TryFrom> for Command { output_file ); return Ok(Command { - command_type: CommandType::Decompression(input_files), + kind: CommandKind::Decompression(input_files), output: Some(File::WithoutExtension(output_file.into())), }); } @@ -130,7 +130,7 @@ impl TryFrom> for Command { // Case 2: error let input_files = process_decompressible_input(input_files)?; return Ok(Command { - command_type: CommandType::Decompression(input_files), + kind: CommandKind::Decompression(input_files), output: None, }); } diff --git a/src/evaluator.rs b/src/evaluator.rs index e69de29..e250f68 100644 --- a/src/evaluator.rs +++ b/src/evaluator.rs @@ -0,0 +1,62 @@ +use std::{convert::TryFrom, path::{PathBuf}}; + +use colored::Colorize; + +use crate::{cli::{Command, CommandKind}, error, extensions::CompressionFormat, file::File}; + +pub struct Evaluator { + command: Command, + // verbosity: Verbosity +} + +impl Evaluator { + pub fn new(command: Command) -> Self { + Self { + command + } + } + + fn handle_compression(files_to_compress: &[PathBuf], output_file: &Option) { + + } + + fn decompress_file(mut filename: &PathBuf, mut extension: CompressionFormat, output_file: &Option) -> error::OuchResult<()> { + loop { + println!("{}: attempting to decompress '{:?}'", "ouch".bright_blue(), filename); + } + } + + fn handle_decompression(files_to_decompress: &[(PathBuf, CompressionFormat)], output_file: &Option) { + for (filename, extension) in files_to_decompress { + // println!("file: {:?}, extension: {:?}", filename, extension); + + // TODO: actually decompress anything ;-; + + // Once decompressed, check if the file can be decompressed further + // e.g.: "foobar.tar.gz" -> "foobar.tar" + + + + let filename: &PathBuf = &filename.as_path().file_stem().unwrap().into(); + match CompressionFormat::try_from(filename) { + Ok(extension) => { + println!("{}: attempting to decompress {:?}, ext: {:?}", "info".yellow(), filename, extension); + }, + Err(err) => { + continue; + } + } + } + } + + pub fn evaluate(&mut self) { + match &self.command.kind { + CommandKind::Compression(files_to_compress) => { + Evaluator::handle_compression(files_to_compress, &self.command.output); + } + CommandKind::Decompression(files_to_decompress) => { + Evaluator::handle_decompression(files_to_decompress, &self.command.output); + } + } + } +} \ No newline at end of file diff --git a/src/extensions.rs b/src/extensions.rs index 227618e..a0ee06e 100644 --- a/src/extensions.rs +++ b/src/extensions.rs @@ -1,12 +1,84 @@ -use std::{ - convert::TryFrom, - path::{Path, PathBuf}, -}; +use std::{convert::TryFrom, ffi::OsStr, path::{Path, PathBuf}}; use crate::error; +use CompressionFormat::*; + +/// Represents the extension of a file, but only really caring about +/// compression formats (and .tar). +/// Ex.: Extension::new("file.tar.gz") == Extension { first_ext: Some(Tar), second_ext: Gzip } +struct Extension { + first_ext: Option, + second_ext: CompressionFormat +} + +impl Extension { + pub fn new(filename: &str) -> error::OuchResult { + let ext_from_str = |ext| { + match ext { + "zip" => Ok(Zip), + "tar" => Ok(Tar), + "gz" => Ok(Gzip), + "bz" => Ok(Bzip), + "lzma" => Ok(Lzma), + other => Err(error::Error::UnknownExtensionError(other.into())), + } + }; + + let (first_ext, second_ext) = match get_extension_from_filename(filename) { + Some(extension_tuple) => { + match extension_tuple { + ("", snd) => (None, snd), + (fst, snd)=> (Some(fst), snd) + } + }, + None => { + return Err(error::Error::MissingExtensionError(filename.into())) + } + }; + + let (first_ext, second_ext) = match (first_ext, second_ext) { + (None, snd) => { + let ext = ext_from_str(snd)?; + (None, ext) + } + (Some(fst), snd) => { + let snd = ext_from_str(snd)?; + let fst = ext_from_str(fst).ok(); + (fst, snd) + } + }; + + Ok( + Self { + first_ext, + second_ext + } + ) + } +} + +pub fn get_extension_from_filename(filename: &str) -> Option<(&str, &str)> { + let path = Path::new(filename); + + let ext = path + .extension() + .and_then(OsStr::to_str)?; + + let previous_extension = path + .file_stem() + .and_then(OsStr::to_str) + .and_then(get_extension_from_filename); + + if let Some((_, prev)) = previous_extension { + Some((prev, ext)) + } else { + Some(("", ext)) + } +} + #[derive(PartialEq, Eq, Debug)] /// Accepted extensions for input and output -pub enum CompressionExtension { +pub enum CompressionFormat { // .gz Gzip, // .bz @@ -22,11 +94,27 @@ pub enum CompressionExtension { // NotCompressed } -impl TryFrom<&PathBuf> for CompressionExtension { +fn extension_from_os_str(ext: &OsStr) -> Result { + + let ext = match ext.to_str() { + Some(str) => str, + None => return Err(error::Error::InvalidUnicode), + }; + + match ext { + "zip" => Ok(Zip), + "tar" => Ok(Tar), + "gz" => Ok(Gzip), + "bz" => Ok(Bzip), + "lzma" => Ok(Lzma), + other => Err(error::Error::UnknownExtensionError(other.into())), + } +} + +impl TryFrom<&PathBuf> for CompressionFormat { type Error = error::Error; fn try_from(ext: &PathBuf) -> Result { - use CompressionExtension::*; let ext = match ext.extension() { Some(ext) => ext, @@ -35,43 +123,20 @@ impl TryFrom<&PathBuf> for CompressionExtension { } }; - let ext = match ext.to_str() { - Some(str) => str, - None => return Err(error::Error::InvalidUnicode), - }; - - match ext { - "zip" => Ok(Zip), - "tar" => Ok(Tar), - "gz" => Ok(Gzip), - "bz" => Ok(Bzip), - "lzma" => Ok(Lzma), - other => Err(error::Error::UnknownExtensionError(other.into())), - } + extension_from_os_str(ext) } } -impl TryFrom<&str> for CompressionExtension { +impl TryFrom<&str> for CompressionFormat { type Error = error::Error; fn try_from(filename: &str) -> Result { - use CompressionExtension::*; - let filename = Path::new(filename); let ext = match filename.extension() { Some(ext) => ext, None => return Err(error::Error::MissingExtensionError(String::new())), }; - let ext = match ext.to_str() { - Some(str) => str, - None => return Err(error::Error::InvalidUnicode), - }; - - match ext { - "zip" => Ok(Zip), - "tar" => Ok(Tar), - other => Err(error::Error::UnknownExtensionError(other.into())), - } + extension_from_os_str(ext) } } diff --git a/src/file.rs b/src/file.rs index 873c945..ead7b68 100644 --- a/src/file.rs +++ b/src/file.rs @@ -1,9 +1,9 @@ use std::path::PathBuf; -use crate::extensions::CompressionExtension; +use crate::extensions::CompressionFormat; #[derive(PartialEq, Eq, Debug)] pub enum File { - WithExtension((PathBuf, CompressionExtension)), + WithExtension((PathBuf, CompressionFormat)), WithoutExtension(PathBuf), } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 3a9b3ce..716579a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,6 @@ -use std::convert::TryFrom; +use std::{convert::TryFrom, ffi::OsStr, path::Path}; + +use colored::Colorize; mod cli; mod error; @@ -8,38 +10,17 @@ mod test; mod evaluator; fn main() { - // Just testing - - // let args: Vec = std::env::args().collect(); - - // let file = std::fs::read(args[1].clone()).unwrap(); - - // match niffler::sniff(Box::new(&file[..])) { - // Ok((reader, compression)) => {}, - // Err(err) => {} + // let matches = cli::get_matches(); + // match cli::Command::try_from(matches) { + // Ok(command) => { + // let mut eval = evaluator::Evaluator::new(command); + // eval.evaluate(); + // } + // Err(err) => { + // print!("{}: {}\n", "error".red(), err); + // } // } - // let (mut reader, compression) = niffler::sniff(Box::new(&file[..])).unwrap(); - - // match compression { - // niffler::Format::Gzip => {} - // niffler::Format::Bzip => {} - // niffler::Format::Lzma => {} - // niffler::Format::No => {} - // } - - // let mut contents = String::new(); - // println!("Contents: {}", reader.read_to_string(&mut contents).unwrap()); - - // dbg!(compression); - - let matches = cli::get_matches(); - match cli::Command::try_from(matches) { - Ok(vals) => { - dbg!(vals); - } - Err(err) => { - print!("{}\n", err); - } - } + dbg!(extensions::get_extension_from_filename("file")); + // dbg!(get_extension_from_filename("file.zip")); } diff --git a/src/test.rs b/src/test.rs index 30c4159..0db972a 100644 --- a/src/test.rs +++ b/src/test.rs @@ -3,9 +3,9 @@ mod cli { use crate::cli::clap_app; use crate::cli::Command; - use crate::cli::CommandType::*; + use crate::cli::CommandKind::*; use crate::error::OuchResult; - use crate::extensions::CompressionExtension::*; + use crate::extensions::CompressionFormat::*; use crate::file::File; use std::convert::TryFrom; @@ -17,7 +17,7 @@ mod cli { assert_eq!( command_from_matches, Command { - command_type: Decompression(vec![("file.zip".into(), Zip,),],), + kind: Decompression(vec![("file.zip".into(), Zip,),],), output: Some(File::WithoutExtension("folder".into())), } ); @@ -33,7 +33,7 @@ mod cli { assert_eq!( command_from_matches, Command { - command_type: Decompression(vec![ + kind: Decompression(vec![ ("file.zip".into(), Zip,), ("file.tar".into(), Tar,), ],), @@ -60,7 +60,7 @@ mod cli { assert_eq!( command_from_matches, Command { - command_type: Compression(vec![ + kind: Compression(vec![ "file".into(), "file2.jpeg".into(), "file3.ok".into() @@ -101,15 +101,15 @@ mod cli_errors { #[cfg(test)] mod extension_extraction { use crate::error::OuchResult; - use crate::extensions::CompressionExtension; + use crate::extensions::CompressionFormat; use std::{convert::TryFrom, path::PathBuf, str::FromStr}; #[test] fn zip() -> OuchResult<()> { let path = PathBuf::from_str("filename.tar.zip").unwrap(); assert_eq!( - CompressionExtension::try_from(&path)?, - CompressionExtension::Zip + CompressionFormat::try_from(&path)?, + CompressionFormat::Zip ); Ok(()) @@ -119,8 +119,8 @@ mod extension_extraction { fn tar() -> OuchResult<()> { let path = PathBuf::from_str("pictures.tar").unwrap(); assert_eq!( - CompressionExtension::try_from(&path)?, - CompressionExtension::Tar + CompressionFormat::try_from(&path)?, + CompressionFormat::Tar ); Ok(()) @@ -130,8 +130,8 @@ mod extension_extraction { fn gz() -> OuchResult<()> { let path = PathBuf::from_str("passwords.tar.gz").unwrap(); assert_eq!( - CompressionExtension::try_from(&path)?, - CompressionExtension::Gzip + CompressionFormat::try_from(&path)?, + CompressionFormat::Gzip ); Ok(()) @@ -141,8 +141,8 @@ mod extension_extraction { fn lzma() -> OuchResult<()> { let path = PathBuf::from_str("mygame.tar.lzma").unwrap(); assert_eq!( - CompressionExtension::try_from(&path)?, - CompressionExtension::Lzma + CompressionFormat::try_from(&path)?, + CompressionFormat::Lzma ); Ok(()) @@ -152,8 +152,8 @@ mod extension_extraction { fn bz() -> OuchResult<()> { let path = PathBuf::from_str("songs.tar.bz").unwrap(); assert_eq!( - CompressionExtension::try_from(&path)?, - CompressionExtension::Bzip + CompressionFormat::try_from(&path)?, + CompressionFormat::Bzip ); Ok(())