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
120
121
122
123
124
125
126
127
128
129
130
131
use mime_guess::MimeGuess;
use std::{fs, io::Read, path::Path};

pub struct FS {}

#[derive(Debug, Clone)]
pub struct File {
    pub path: String,
    pub metadata: fs::Metadata,
    pub file_type: fs::FileType,
    pub content: Option<Vec<u8>>,
    pub content_type: Option<String>,
    pub buffer: Option<Vec<u8>>,
}

impl File {
    pub fn from_dir_entry(path: String, dir_entry: &fs::DirEntry) -> File {
        let mut content: Option<Vec<u8>> = None;
        let metadata = dir_entry.metadata().unwrap();
        let mut content_type: Option<String> = None;
        let buffer: Option<Vec<u8>> = None;

        if metadata.clone().is_file() {
            let is_other_type_extension = if let Some(extension) = path.rsplit('.').next() {
                !(extension.to_lowercase() == "html") || !(extension.to_lowercase() == "hbs")
            } else {
                false
            };

            if is_other_type_extension {
                content = Some(FS::read_to_buf(&path))
            } else {
                content = Some(FS::read_to_string(&path));
            }

            content_type = Some(FS::get_mime_type(path.as_str()));
        }

        File {
            path,
            metadata,
            file_type: dir_entry.file_type().unwrap().clone(),
            content,
            content_type,
            buffer,
        }
    }
}

impl FS {
    /// Return a Vec for All files in directory
    ///
    /// # Arguments
    ///
    /// * `path` - Path where the file is located
    ///
    /// # Examples
    ///
    /// ```rust
    /// use FS;
    ///
    /// fn (){
    ///     let resources = FS::get_all_in_directories("resources");
    /// }
    /// ```
    pub fn get_all_in_directories(path: &str) -> Vec<File> {
        let directory_root = fs::read_dir(path).unwrap();
        let mut directories_dir_entry = Vec::new();
        let mut directories: Vec<File> = Vec::new();

        for directory in directory_root {
            directories_dir_entry.push(directory.unwrap())
        }

        for directory in &directories_dir_entry {
            let path = String::from(directory.path().clone().to_str().unwrap());

            directories.push(File::from_dir_entry(path, directory));
        }

        directories
    }

    /// Read a file and convert to String
    ///
    /// # Arguments
    ///
    /// * `path` - Path to read file
    ///
    /// # Examples
    ///
    /// ```rust
    /// use FS;
    ///
    /// let file = FS::read_to_string("main.js");
    /// ```
    pub fn read_to_hex(path: &str) -> String {
        let mut file = fs::File::open(path).expect("No se pudo abrir el archivo");
        let mut buffer = Vec::new();
        file.read_to_end(&mut buffer)
            .expect("Error al leer el archivo");

        let hex_string: String = buffer.iter().map(|byte| format!("{:02X}", byte)).collect();

        hex_string
    }

    pub fn read_to_buf(path: &str) -> Vec<u8> {
        let mut file = fs::File::open(path).expect("No se pudo abrir el archivo");
        let mut buffer = Vec::new();
        file.read_to_end(&mut buffer)
            .expect("Error al leer el archivo");

        buffer
    }

    pub fn read_to_string(path: &str) -> Vec<u8> {
        match fs::read_to_string(path) {
            Ok(content) => content.as_bytes().into(),
            Err(_) => FS::read_to_buf(path),
        }
    }

    fn get_mime_type(path: &str) -> String {
        let path = Path::new(path);

        MimeGuess::from_path(path)
            .first_or_octet_stream()
            .to_string()
    }
}