bitcasky_common/fs/
file_type.rs

1use core::panic;
2use std::path::{Path, PathBuf};
3
4use crate::storage_id::StorageId;
5
6const LOCK_FILE_EXTENSION: &str = "lock";
7const MERGE_META_FILE_EXTENSION: &str = "meta";
8const DATA_FILE_EXTENSION: &str = "data";
9const HINT_FILE_EXTENSION: &str = "hint";
10
11#[derive(PartialEq, Eq, Debug, Copy, Clone)]
12pub enum FileType {
13    Unknown,
14    LockFile,
15    MergeMeta,
16    DataFile,
17    HintFile,
18}
19
20impl FileType {
21    pub fn get_path<P: AsRef<Path>>(&self, base_dir: P, storage_id: Option<StorageId>) -> PathBuf {
22        base_dir.as_ref().join(match self {
23            Self::LockFile => format!("bitcask.{}", LOCK_FILE_EXTENSION),
24            Self::MergeMeta => format!("merge.{}", MERGE_META_FILE_EXTENSION),
25            Self::DataFile => format!("{}.{}", storage_id.unwrap(), DATA_FILE_EXTENSION),
26            Self::HintFile => format!("{}.{}", storage_id.unwrap(), HINT_FILE_EXTENSION),
27            Self::Unknown => panic!("get path for unknown data type"),
28        })
29    }
30
31    pub fn check_file_belongs_to_type(&self, file_path: &Path) -> bool {
32        let ft = match file_path.extension() {
33            None => FileType::Unknown,
34            Some(os_str) => match os_str.to_str() {
35                Some(LOCK_FILE_EXTENSION) => FileType::LockFile,
36                Some(MERGE_META_FILE_EXTENSION) => FileType::MergeMeta,
37                Some(DATA_FILE_EXTENSION) => FileType::DataFile,
38                Some(HINT_FILE_EXTENSION) => FileType::HintFile,
39                _ => FileType::Unknown,
40            },
41        };
42        *self == ft
43    }
44
45    pub fn parse_storage_id_from_file_name(&self, file_path: &Path) -> Option<StorageId> {
46        let binding = file_path.file_name().unwrap().to_string_lossy();
47        let (storage_id_str, _) = binding.split_at(binding.len() - self.extension().len() - 1);
48        match self {
49            Self::LockFile => None,
50            Self::MergeMeta => None,
51            Self::DataFile => Some(storage_id_str),
52            Self::HintFile => Some(storage_id_str),
53            Self::Unknown => panic!("get path for unknown data type"),
54        }
55        .map(|storage_id_str| storage_id_str.parse::<StorageId>())
56        .transpose()
57        .unwrap_or(None)
58    }
59
60    fn extension(&self) -> &str {
61        match self {
62            Self::LockFile => LOCK_FILE_EXTENSION,
63            Self::MergeMeta => MERGE_META_FILE_EXTENSION,
64            Self::DataFile => DATA_FILE_EXTENSION,
65            Self::HintFile => HINT_FILE_EXTENSION,
66            Self::Unknown => panic!("get path for unknown data type"),
67        }
68    }
69}
70
71impl std::fmt::Display for FileType {
72    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
73        match self {
74            FileType::Unknown => f.write_str("Unknown"),
75            FileType::LockFile => f.write_str("LockFile"),
76            FileType::MergeMeta => f.write_str("MergeMetaFile"),
77            FileType::DataFile => f.write_str("DataFile"),
78            FileType::HintFile => f.write_str("HintFile"),
79        }
80    }
81}
82
83#[cfg(test)]
84mod tests {
85    use super::*;
86    use utilities::common::get_temporary_directory_path;
87
88    #[test]
89    fn test_file_type() {
90        let dir = get_temporary_directory_path();
91
92        let p = FileType::LockFile.get_path(&dir, None);
93        assert!(FileType::LockFile.check_file_belongs_to_type(&p));
94        let p = FileType::HintFile.get_path(&dir, Some(123));
95        assert!(FileType::HintFile.check_file_belongs_to_type(&p));
96        let p = FileType::DataFile.get_path(&dir, Some(100));
97        assert!(FileType::DataFile.check_file_belongs_to_type(&p));
98        let p = FileType::MergeMeta.get_path(&dir, Some(100));
99        assert!(FileType::MergeMeta.check_file_belongs_to_type(&p));
100
101        assert!(!FileType::LockFile.check_file_belongs_to_type(&dir.join("")));
102        assert!(!FileType::DataFile.check_file_belongs_to_type(&dir.join("")));
103        assert!(!FileType::HintFile.check_file_belongs_to_type(&dir.join("")));
104        assert!(!FileType::MergeMeta.check_file_belongs_to_type(&dir.join("")));
105
106        assert!(!FileType::LockFile.check_file_belongs_to_type(&dir.join(".abc")));
107        assert!(!FileType::DataFile.check_file_belongs_to_type(&dir.join(".abc")));
108        assert!(!FileType::HintFile.check_file_belongs_to_type(&dir.join(".abc")));
109        assert!(!FileType::MergeMeta.check_file_belongs_to_type(&dir.join(".abc")));
110    }
111}