rusty_files/utils/
mime.rs

1use mime_guess::MimeGuess;
2use std::path::Path;
3
4pub fn detect_mime_type<P: AsRef<Path>>(path: P) -> Option<String> {
5    let guess = MimeGuess::from_path(path.as_ref());
6    guess.first().map(|m| m.to_string())
7}
8
9pub fn is_text_mime(mime: &str) -> bool {
10    mime.starts_with("text/") || is_code_mime(mime)
11}
12
13pub fn is_code_mime(mime: &str) -> bool {
14    matches!(
15        mime,
16        "application/javascript"
17            | "application/json"
18            | "application/xml"
19            | "application/x-sh"
20            | "application/x-python"
21            | "application/x-ruby"
22            | "application/x-perl"
23            | "application/x-php"
24    )
25}
26
27pub fn is_image_mime(mime: &str) -> bool {
28    mime.starts_with("image/")
29}
30
31pub fn is_video_mime(mime: &str) -> bool {
32    mime.starts_with("video/")
33}
34
35pub fn is_audio_mime(mime: &str) -> bool {
36    mime.starts_with("audio/")
37}
38
39pub fn is_archive_mime(mime: &str) -> bool {
40    matches!(
41        mime,
42        "application/zip"
43            | "application/x-tar"
44            | "application/gzip"
45            | "application/x-bzip2"
46            | "application/x-7z-compressed"
47            | "application/x-rar-compressed"
48    )
49}
50
51pub fn categorize_file<P: AsRef<Path>>(path: P) -> FileCategory {
52    if let Some(mime) = detect_mime_type(path) {
53        if is_text_mime(&mime) || is_code_mime(&mime) {
54            FileCategory::Text
55        } else if is_image_mime(&mime) {
56            FileCategory::Image
57        } else if is_video_mime(&mime) {
58            FileCategory::Video
59        } else if is_audio_mime(&mime) {
60            FileCategory::Audio
61        } else if is_archive_mime(&mime) {
62            FileCategory::Archive
63        } else {
64            FileCategory::Other
65        }
66    } else {
67        FileCategory::Unknown
68    }
69}
70
71#[derive(Debug, Clone, Copy, PartialEq, Eq)]
72pub enum FileCategory {
73    Text,
74    Image,
75    Video,
76    Audio,
77    Archive,
78    Other,
79    Unknown,
80}
81
82#[cfg(test)]
83mod tests {
84    use super::*;
85
86    #[test]
87    fn test_detect_mime_type() {
88        assert!(detect_mime_type("test.txt").is_some());
89        assert!(detect_mime_type("test.rs").is_some());
90        assert!(detect_mime_type("test.png").is_some());
91    }
92
93    #[test]
94    fn test_is_text_mime() {
95        assert!(is_text_mime("text/plain"));
96        assert!(is_text_mime("text/html"));
97        assert!(!is_text_mime("image/png"));
98    }
99
100    #[test]
101    fn test_categorize_file() {
102        assert_eq!(categorize_file("test.txt"), FileCategory::Text);
103        assert_eq!(categorize_file("test.png"), FileCategory::Image);
104        assert_eq!(categorize_file("test.mp4"), FileCategory::Video);
105        assert_eq!(categorize_file("test.mp3"), FileCategory::Audio);
106        assert_eq!(categorize_file("test.zip"), FileCategory::Archive);
107    }
108}