lotus_lib/package/
package.rs

1use std::path::PathBuf;
2
3use crate::cache_pair::CachePair;
4
5use super::package_type::PackageType;
6
7/// A package containing three cache pairs.
8pub struct Package<T: CachePair> {
9    directory: PathBuf,
10    name: String,
11    is_post_ensmallening: bool,
12
13    h_package: Option<T>,
14    f_package: Option<T>,
15    b_package: Option<T>,
16}
17
18impl<T: CachePair> Package<T> {
19    pub(super) fn new<P>(directory: P, name: String, is_post_ensmallening: bool) -> Self
20    where
21        P: Into<PathBuf>,
22    {
23        let directory = directory.into();
24
25        let h_package = Package::<T>::new_package(&directory, &name, is_post_ensmallening, 'H');
26        let f_package = Package::<T>::new_package(&directory, &name, is_post_ensmallening, 'F');
27        let b_package = Package::<T>::new_package(&directory, &name, is_post_ensmallening, 'B');
28        Self {
29            directory,
30            name,
31            is_post_ensmallening,
32            h_package,
33            f_package,
34            b_package,
35        }
36    }
37
38    /// Creates a new package from the specified directory, name, and type.
39    ///
40    /// Returns `None` if the package does not exist.
41    fn new_package<P, I>(
42        directory: P,
43        name: &str,
44        is_post_ensmallening: bool,
45        trio_type: I,
46    ) -> Option<T>
47    where
48        P: Into<PathBuf>,
49        I: TryInto<PackageType>,
50    {
51        let directory = directory.into();
52
53        let mut toc_path = directory.clone();
54        let mut cache_path = directory.clone();
55
56        let trio_type = trio_type.try_into().ok()?;
57        let trio_type = char::from(trio_type);
58
59        toc_path.push(format!("{}.{}.toc", trio_type, name));
60        cache_path.push(format!("{}.{}.cache", trio_type, name));
61
62        if !toc_path.exists() && !cache_path.exists() {
63            return None;
64        }
65        Some(T::new(toc_path, cache_path, is_post_ensmallening))
66    }
67
68    /// Returns the directory of the package.
69    pub fn directory(&self) -> &PathBuf {
70        &self.directory
71    }
72
73    /// Returns the name of the package.
74    pub fn name(&self) -> &String {
75        &self.name
76    }
77
78    /// Returns whether the package is post-ensmallening.
79    ///
80    /// This is used to determine how to decompress the data from before "The Great Ensmallening"
81    /// update of Warframe.
82    pub fn is_post_ensmallening(&self) -> bool {
83        self.is_post_ensmallening
84    }
85
86    /// Returns a reference to the package of the specified type.
87    ///
88    /// Returns `None` if the package does not exist.
89    pub fn borrow<I>(&self, package_type: I) -> Option<&T>
90    where
91        I: TryInto<PackageType>,
92    {
93        match package_type.try_into() {
94            Ok(PackageType::H) => self.h_package.as_ref(),
95            Ok(PackageType::F) => self.f_package.as_ref(),
96            Ok(PackageType::B) => self.b_package.as_ref(),
97            Err(_) => None,
98        }
99    }
100
101    /// Returns a mutable reference to the package of the specified type.
102    ///
103    /// Returns `None` if the package does not exist.
104    pub fn borrow_mut<I>(&mut self, package_type: I) -> Option<&mut T>
105    where
106        I: TryInto<PackageType>,
107    {
108        match package_type.try_into() {
109            Ok(PackageType::H) => self.h_package.as_mut(),
110            Ok(PackageType::F) => self.f_package.as_mut(),
111            Ok(PackageType::B) => self.b_package.as_mut(),
112            Err(_) => None,
113        }
114    }
115
116    /// Returns the package of the specified type.
117    pub fn take<I>(&mut self, package_type: I) -> Option<T>
118    where
119        I: TryInto<PackageType>,
120    {
121        match package_type.try_into() {
122            Ok(PackageType::H) => self.h_package.take(),
123            Ok(PackageType::F) => self.f_package.take(),
124            Ok(PackageType::B) => self.b_package.take(),
125            Err(_) => None,
126        }
127    }
128}