1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#![cfg_attr(feature = "cargo-clippy", deny(clippy))]
#![deny(missing_debug_implementations, missing_docs, warnings)]

//! # unwalk-base
//!
//! Provide un-gzip implementation as the action on matching files.

extern crate file;
extern crate filebuffer;
extern crate flate2;
extern crate unwalk_base;

use filebuffer::FileBuffer;
use flate2::read::GzDecoder;
use std::io::Read;
use std::path::Path;
use unwalk_base::{Action, ActionResult};

/// Implementation for un-gzip action.
#[derive(Debug)]
pub struct GzAction;

impl Action for GzAction {
    fn execute<P>(path: P) -> ActionResult
    where
        P: AsRef<Path>,
    {
        let path = path.as_ref();
        let buf = FileBuffer::open(path)?;
        let mut decoder = GzDecoder::new(buf.as_ref());

        let mut s = String::new();
        decoder.read_to_string(&mut s)?;

        let output_path = path.with_extension("");
        file::put(&output_path, s.as_bytes())?;

        Ok(())
    }

    fn default_extensions() -> &'static [&'static str] {
        &["gz"]
    }
}

#[cfg(test)]
mod tests {
    extern crate tempfile;

    use self::tempfile::NamedTempFile;
    use super::*;
    use flate2::Compression;
    use flate2::write::GzEncoder;
    use std::io::{self, Write};

    fn write_compressed_bytes<B>(bytes: B) -> io::Result<Vec<u8>>
    where
        B: AsRef<[u8]>,
    {
        let mut encoder = GzEncoder::new(Vec::new(), Compression::default());
        encoder.write_all(bytes.as_ref())?;
        encoder.finish()
    }

    fn write_tmpfile_bytes_wrapper<B>(bytes: B, compress: bool) -> ActionResult
    where
        B: AsRef<[u8]>,
    {
        let tmpfile = NamedTempFile::new();
        assert!(tmpfile.is_ok());
        let mut tmpfile = tmpfile.unwrap();

        let bytes = bytes.as_ref();

        let write_res = if compress {
            let compressed_bytes = write_compressed_bytes(bytes);
            assert!(compressed_bytes.is_ok());
            let compressed_bytes = compressed_bytes.unwrap();

            tmpfile.write_all(&compressed_bytes)
        } else {
            tmpfile.write_all(bytes)
        };

        assert!(write_res.is_ok());

        let path = tmpfile.into_temp_path();
        let exec_res = GzAction::execute(&path);

        let close_res = path.close();
        assert!(close_res.is_ok());

        exec_res
    }

    #[test]
    fn test_gz_action_execute_ok_1() {
        let exec_res = write_tmpfile_bytes_wrapper(b"", true);
        assert!(exec_res.is_ok());
    }

    #[test]
    fn test_gz_action_execute_ok_2() {
        let exec_res = write_tmpfile_bytes_wrapper(b"Hello World!", true);
        assert!(exec_res.is_ok());
    }

    #[test]
    fn test_gz_action_execute_fail_1() {
        let exec_res = write_tmpfile_bytes_wrapper(b"", false);
        assert!(exec_res.is_err());
    }

    #[test]
    fn test_gz_action_execute_fail_2() {
        let exec_res = write_tmpfile_bytes_wrapper(b"Hello World!", false);
        assert!(exec_res.is_err());
    }
}