rs2cache/
store.rs

1use self::{disk_store::DiskStore, flat_file_store::FlatFileStore};
2use std::path::Path;
3use thiserror::Error;
4
5pub mod disk_store;
6pub mod flat_file_store;
7
8const DATA_PATH: &str = "main_file_cache.dat2";
9const LEGACY_DATA_PATH: &str = "main_file_cache.dat2";
10pub const ARCHIVESET: u8 = 255;
11
12#[derive(Error, Debug)]
13pub enum StoreError {
14    #[error("io error: {0}")]
15    Io(#[from] std::io::Error),
16    #[error("disk_store error {0}")]
17    DiskStore(#[from] disk_store::DiskStoreError),
18    #[error("group shorter than expected")]
19    GroupTooShort,
20    #[error("next block is outside the data file")]
21    NextBlockOutsideDataFile,
22    #[error("expecting group {0}, was {1}")]
23    GroupMismatch(u32, u32),
24    #[error("expecting block number {0}, was {1}")]
25    BlockMismatch(u16, u16),
26    #[error("expecting archive {0}, was {1}")]
27    ArchiveMismatch(u8, u8),
28}
29
30/// The store is responsible for reading and writing data of the various RS2 formats.
31pub trait Store {
32    fn list(&self, archive: u8) -> Result<Vec<u32>, StoreError>;
33    fn read(&self, archive: u8, group: u32) -> Result<Vec<u8>, StoreError>;
34}
35
36pub fn store_open(path: &str) -> Result<Box<dyn Store>, StoreError> {
37    let has_data_file = Path::new(&path).join(DATA_PATH).exists();
38    let has_legacy_data_file = Path::new(path).join(LEGACY_DATA_PATH).exists();
39
40    if has_data_file || has_legacy_data_file {
41        Ok(Box::new(DiskStore::open(path)?))
42    } else {
43        Ok(Box::new(FlatFileStore::open(path)?))
44    }
45}