casc_storage/index/
index_file.rs

1//! Generic index file handling
2
3use crate::error::Result;
4use crate::types::{ArchiveLocation, EKey};
5use std::path::Path;
6
7/// Version of the index format
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum IndexVersion {
10    V5, // Older format
11    V7, // Current format
12}
13
14/// Generic index file interface
15pub struct IndexFile {
16    version: IndexVersion,
17    entries: std::collections::BTreeMap<EKey, ArchiveLocation>,
18}
19
20impl IndexFile {
21    /// Create a new empty index
22    pub fn new(version: IndexVersion) -> Self {
23        Self {
24            version,
25            entries: std::collections::BTreeMap::new(),
26        }
27    }
28
29    /// Load an index from a file
30    pub fn load(path: &Path) -> Result<Self> {
31        // Determine type based on extension
32        if path.extension().and_then(|s| s.to_str()) == Some("idx") {
33            let parser = super::IdxParser::parse_file(path)?;
34            let mut entries = std::collections::BTreeMap::new();
35            for (ekey, location) in parser.entries() {
36                entries.insert(*ekey, *location);
37            }
38            Ok(Self {
39                version: IndexVersion::V7,
40                entries,
41            })
42        } else if path.extension().and_then(|s| s.to_str()) == Some("index") {
43            let parser = super::GroupIndex::parse_file(path)?;
44            let mut entries = std::collections::BTreeMap::new();
45            for (ekey, location) in parser.entries() {
46                entries.insert(*ekey, *location);
47            }
48            Ok(Self {
49                version: IndexVersion::V7,
50                entries,
51            })
52        } else {
53            Err(crate::error::CascError::InvalidIndexFormat(format!(
54                "Unknown index file extension: {:?}",
55                path.extension()
56            )))
57        }
58    }
59
60    /// Look up an entry by EKey
61    pub fn lookup(&self, ekey: &EKey) -> Option<&ArchiveLocation> {
62        self.entries.get(ekey)
63    }
64
65    /// Add an entry to the index
66    pub fn add_entry(&mut self, ekey: EKey, location: ArchiveLocation) {
67        self.entries.insert(ekey, location);
68    }
69
70    /// Remove an entry from the index
71    pub fn remove_entry(&mut self, ekey: &EKey) -> Option<ArchiveLocation> {
72        self.entries.remove(ekey)
73    }
74
75    /// Get the number of entries
76    pub fn len(&self) -> usize {
77        self.entries.len()
78    }
79
80    /// Check if the index is empty
81    pub fn is_empty(&self) -> bool {
82        self.entries.is_empty()
83    }
84
85    /// Get the index version
86    pub fn version(&self) -> IndexVersion {
87        self.version
88    }
89
90    /// Iterate over all entries
91    pub fn entries(&self) -> impl Iterator<Item = (&EKey, &ArchiveLocation)> {
92        self.entries.iter()
93    }
94}