summaryrefslogtreecommitdiff
path: root/src/entry.rs
blob: 2679e424a1389e60bdfad95649651f1639f8c1bd (plain) (blame)
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
use crate::EntryReadError;
use std::path::{Path, PathBuf};

#[derive(PartialEq)]
pub enum EntryType {
    File,
    Directory,
}

pub struct Entry {
    pub entry_type: EntryType,
    pub is_symlink: bool,
    pub name: String,
    pub extension: String,
    pub path: PathBuf,
    pub original_path: PathBuf,
}
impl Entry {
    pub fn from_path<P: AsRef<Path>>(path: P) -> Result<Self, EntryReadError> {
        let path = path.as_ref();
        let metadata = path.metadata()?;
        let canonical_path = std::fs::canonicalize(path)?;
        let canonical_metadata = canonical_path.metadata()?;
        let entry_type = if canonical_metadata.is_file() {
            EntryType::File
        } else if canonical_metadata.is_dir() {
            EntryType::Directory
        } else {
            return Err(EntryReadError::NotFound);
        };

        let name = match path.file_name() {
            Some(osstr) => osstr.to_string_lossy().to_string(),
            None => unreachable!(),
        };
        let extension = match path.extension() {
            Some(extension) => extension.to_string_lossy().into(),
            None => String::default(),
        };
        Ok(Entry {
            entry_type,
            name,
            extension,
            path: canonical_path,
            original_path: path.to_path_buf(),
            is_symlink: metadata.is_symlink(),
        })
    }

    /// Splits the filename on the last period, ignoring any period at the
    /// start of the filename. If no extension is found, the extension is empty.
    pub fn split_name(&self) -> (String, String) {
        match self.name.rsplit_once(".") {
            Some(("", _)) | None => (self.name.to_string(), String::new()),
            Some((prefix, extension)) => (prefix.to_string(), extension.to_string()),
        }
    }

    pub fn is_file(&self) -> bool {
        match self.entry_type {
            EntryType::File => true,
            _ => false,
        }
    }

    pub fn is_directory(&self) -> bool {
        match self.entry_type {
            EntryType::Directory => true,
            _ => false,
        }
    }

    pub fn read_as_bytes(&self) -> Result<Vec<u8>, EntryReadError> {
        return Ok(std::fs::read(&self.path)?);
    }

    pub fn read_as_utf8_string(&self) -> Result<String, EntryReadError> {
        return Ok(String::from_utf8_lossy(&self.read_as_bytes()?).to_string());
    }
}

impl AsRef<Path> for Entry {
    fn as_ref(&self) -> &Path {
        &self.path
    }
}