fs-encrypt 0.1.3

CLI tool for file encryption/decryption
Documentation
//! # fs-encrypt
//!
//! A CLI tool to encrypt/decrypt files and directories.
//!
//! ## Usage
//! `fs-encrypt [encrypt | decrypt] [input_path] [output_path]`

use std::error::Error;

mod args;
mod encrypt;
mod files;

/// Parses raw CLI arguments to a formatted `Args` struct.
pub fn parse_arguments(args: impl Iterator<Item = String>) -> Result<args::Args, &'static str> {
    args::Args::arguments(args)
}

/// Encrypts or decrypts files and directories given arguments.
///
/// `input_path` and `output_path` can be either files or directories,
/// and the `input_path` file type will be used to determine the operation.
pub fn run(args: args::Args) -> Result<(), Box<dyn Error>> {
    let cipher = encrypt::Cipher::new(&args.password);
    let filepaths = files::get_filepaths(args.input_path, args.output_path)?;

    for path in filepaths {
        let contents = files::read_file(&path.input_path)?;

        let transformed = cipher.apply_codec(contents, &args.codec_type);
        files::write_file(&path.output_path, transformed)?;
    }

    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::fs;

    #[test]
    fn test_transform_integration() {
        let inner_contents = b"
The Matrix is everywhere. It is all around us. Even now,
in this very room. You can see it when you look out your
window or when you turn on your television"
            .to_vec();

        let base_contents = b"
You can feel it when you go to work... when you go to
church... when you pay your taxes. It is the world that
has been pulled over your eyes to blind you from the truth."
            .to_vec();

        let base_dir_path = String::from("./tests/directory");

        let input_dir_path = files::extend_dir_path(&base_dir_path, "input");
        let enc_dir_path = files::extend_dir_path(&base_dir_path, "encrypted");
        let dec_dir_path = files::extend_dir_path(&base_dir_path, "decrypted");

        let inner_file_ext = "go/to/zion.txt";
        let inner_file_path = files::extend_dir_path(&input_dir_path, inner_file_ext);
        files::write_file(&inner_file_path, inner_contents.clone()).unwrap();

        let base_file_ext = "machine-city.txt";
        let base_file_path = files::extend_dir_path(&input_dir_path, base_file_ext);
        files::write_file(&base_file_path, base_contents.clone()).unwrap();

        let password = String::from("red pill or blue pill?");

        let enc_args = args::Args {
            codec_type: args::CodecType::Encrypt,
            input_path: input_dir_path.clone(),
            output_path: enc_dir_path.clone(),
            password: password.clone(),
        };
        run(enc_args).unwrap();

        let dec_args = args::Args {
            codec_type: args::CodecType::Decrypt,
            input_path: enc_dir_path,
            output_path: dec_dir_path.clone(),
            password: password,
        };
        run(dec_args).unwrap();

        let dec_inner_file_path = files::extend_dir_path(&dec_dir_path, inner_file_ext);
        let dec_inner_contents = files::read_file(&dec_inner_file_path).unwrap();
        assert_eq!(dec_inner_contents, inner_contents);

        let dec_base_file_path = files::extend_dir_path(&dec_dir_path, base_file_ext);
        let dec_base_contents = files::read_file(&dec_base_file_path).unwrap();
        assert_eq!(dec_base_contents, base_contents);

        fs::remove_dir_all(&base_dir_path).unwrap();
    }
}