Add struct Extension

This commit is contained in:
Vinícius Rodrigues Miguel 2021-03-20 18:58:26 -03:00
parent 73398c2d50
commit 7fd6020d99
6 changed files with 201 additions and 93 deletions

View File

@ -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<PathBuf>,
),
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<File>,
}
@ -66,7 +66,7 @@ impl TryFrom<clap::ArgMatches<'static>> for Command {
fn try_from(matches: clap::ArgMatches<'static>) -> error::OuchResult<Command> {
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<clap::ArgMatches<'static>> 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<clap::ArgMatches<'static>> 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<clap::ArgMatches<'static>> 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<clap::ArgMatches<'static>> 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,
});
}

View File

@ -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<File>) {
}
fn decompress_file(mut filename: &PathBuf, mut extension: CompressionFormat, output_file: &Option<File>) -> error::OuchResult<()> {
loop {
println!("{}: attempting to decompress '{:?}'", "ouch".bright_blue(), filename);
}
}
fn handle_decompression(files_to_decompress: &[(PathBuf, CompressionFormat)], output_file: &Option<File>) {
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);
}
}
}
}

View File

@ -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<CompressionFormat>,
second_ext: CompressionFormat
}
impl Extension {
pub fn new(filename: &str) -> error::OuchResult<Self> {
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<CompressionFormat, error::Error> {
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<Self, Self::Error> {
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<Self, Self::Error> {
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)
}
}

View File

@ -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),
}

View File

@ -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<String> = 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"));
}

View File

@ -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(())