libwaj/
waj.rs

1use crate::error::{BaseError, WajError, WajFormatError};
2
3use super::common::{AllProperties, Comparator, Entry, FullBuilderTrait, RealBuilder};
4use jbk::reader::Range;
5use std::path::Path;
6
7pub struct Waj {
8    container: jbk::reader::Container,
9    pub(crate) root_index: jbk::reader::Index,
10    pub(crate) properties: AllProperties,
11}
12
13impl std::ops::Deref for Waj {
14    type Target = jbk::reader::Container;
15    fn deref(&self) -> &Self::Target {
16        &self.container
17    }
18}
19
20fn create_properties(
21    container: &jbk::reader::Container,
22    index: &jbk::reader::Index,
23) -> Result<AllProperties, BaseError> {
24    AllProperties::new(
25        index.get_store(container.get_entry_storage())?,
26        container.get_value_storage(),
27    )
28}
29
30impl Waj {
31    pub fn new<P: AsRef<Path>>(file: P) -> Result<Self, WajError> {
32        let container = jbk::reader::Container::new(&file)?;
33        let root_index = container
34            .get_directory_pack()
35            .get_index_from_name("waj_entries")?
36            .ok_or(WajFormatError("No `waj_entries` in the archive"))?;
37        let properties = create_properties(&container, &root_index)?;
38
39        Ok(Self {
40            container,
41            root_index,
42            properties,
43        })
44    }
45
46    pub fn create_properties(
47        &self,
48        index: &jbk::reader::Index,
49    ) -> Result<AllProperties, BaseError> {
50        create_properties(&self.container, index)
51    }
52
53    pub fn get_entry<B>(&self, path: &str) -> Result<Entry<B::Entry>, WajError>
54    where
55        B: FullBuilderTrait,
56    {
57        let comparator = Comparator::new(&self.properties);
58        let builder = RealBuilder::<B>::new(&self.properties);
59        let current_range: jbk::EntryRange = (&self.root_index).into();
60        let comparator = comparator.compare_with(path.as_bytes());
61        match current_range.find(&comparator)? {
62            None => Err(WajError::PathNotFound(format!("Cannot found entry {path}"))),
63            Some(idx) => {
64                let entry = current_range
65                    .get_entry(&builder, idx)?
66                    .expect("idx should be valid");
67                Ok(entry)
68            }
69        }
70    }
71}