emote_psb/
lib.rs

1/*
2 * Created on Fri Dec 25 2020
3 *
4 * Copyright (c) storycraft. Licensed under the MIT Licence.
5 */
6
7pub mod types;
8
9pub mod header;
10pub mod offsets;
11
12pub mod reader;
13pub mod writer;
14
15mod internal;
16
17pub use reader::PsbReader;
18pub use writer::PsbWriter;
19
20use header::PsbHeader;
21use io::Seek;
22use offsets::{PsbOffsets, PsbResourcesOffset};
23use types::{PsbValue, collection::PsbObject};
24
25use std::{error::Error, io::{self, Read, SeekFrom}};
26
27/// psb file signature
28pub const PSB_SIGNATURE: u32 = 0x425350;
29
30/// compressed psb file signature
31pub const PSB_MDF_SIGNATURE: u32 = 0x66646D;
32
33#[derive(Debug)]
34pub struct PsbError {
35
36    kind: PsbErrorKind,
37    err: Option<Box<dyn Error>>
38
39}
40
41impl PsbError {
42
43    pub fn new(kind: PsbErrorKind, err: Option<Box<dyn Error>>) -> Self {
44        Self { kind, err }
45    }
46
47    pub fn kind(&self) -> &PsbErrorKind {
48        &self.kind
49    }
50
51    pub fn source(&self) -> &Option<Box<dyn Error>> {
52        &self.err
53    }
54
55}
56
57#[derive(Debug)]
58pub enum PsbErrorKind {
59
60    Io(io::Error),
61    InvalidFile,
62    InvalidHeader,
63    UnknownHeaderVersion,
64    InvalidIndex,
65    InvalidPSBValue,
66    InvalidPSBRoot,
67    InvalidOffsetTable,
68    Custom
69
70}
71
72impl From<io::Error> for PsbError {
73
74    fn from(err: io::Error) -> Self {
75        PsbError::new(PsbErrorKind::Io(err), None)
76    }
77
78}
79
80#[derive(Debug, Clone)]
81pub struct PsbRefs {
82
83    names: Vec<String>,
84
85    strings: Vec<String>,
86
87}
88
89impl PsbRefs {
90
91    pub fn new(names: Vec<String>, strings: Vec<String>) -> Self {
92        Self {
93            names, strings
94        }
95    }
96
97    pub fn names(&self) -> &Vec<String> {
98        &self.names
99    }
100
101    pub fn names_mut(&mut self) -> &mut Vec<String> {
102        &mut self.names
103    }
104
105    pub fn names_len(&self) -> usize {
106        self.names.len()
107    }
108
109    pub fn get_name(&self, index: usize) -> Option<&String> {
110        self.names.get(index)
111    }
112
113    pub fn get_name_mut(&mut self, index: usize) -> Option<&mut String> {
114        self.names.get_mut(index)
115    }
116
117    pub fn find_name_index(&self, name: &String) -> Option<u64> {
118        for (i, nm) in self.names.iter().enumerate() {
119            if nm == name {
120                return Some(i as u64)
121            }
122        }
123
124        None
125    }
126
127    pub fn strings(&self) -> &Vec<String> {
128        &self.strings
129    }
130
131    pub fn strings_mut(&mut self) -> &mut Vec<String> {
132        &mut self.strings
133    }
134
135    pub fn strings_len(&self) -> usize {
136        self.strings.len()
137    }
138
139    pub fn get_string(&self, index: usize) -> Option<&String> {
140        self.strings.get(index)
141    }
142
143    pub fn get_string_mut(&mut self, index: usize) -> Option<&mut String> {
144        self.strings.get_mut(index)
145    }
146
147    pub fn find_string_index(&self, string: &String) -> Option<u64> {
148        for (i, st) in self.strings.iter().enumerate() {
149            if st == string {
150                return Some(i as u64)
151            }
152        }
153
154        None
155    }
156}
157
158#[derive(Debug)]
159pub struct VirtualPsb {
160
161    header: PsbHeader,
162
163    resources: Vec<Vec<u8>>,
164    extra: Vec<Vec<u8>>,
165
166    root: PsbObject
167
168}
169
170impl VirtualPsb {
171
172    pub fn new(
173        header: PsbHeader,
174        resources: Vec<Vec<u8>>,
175        extra: Vec<Vec<u8>>,
176        root: PsbObject
177    ) -> Self {
178        Self {
179            header,
180            resources,
181            extra,
182            root
183        }
184    }
185
186    pub fn header(&self) -> PsbHeader {
187        self.header
188    }
189
190    pub fn resources(&self) -> &Vec<Vec<u8>> {
191        &self.resources
192    }
193
194    pub fn resources_mut(&mut self) -> &mut Vec<Vec<u8>> {
195        &mut self.resources
196    }
197
198    pub fn extra(&self) -> &Vec<Vec<u8>> {
199        &self.extra
200    }
201
202    pub fn extra_mut(&mut self) -> &mut Vec<Vec<u8>> {
203        &mut self.extra
204    }
205
206    pub fn root(&self) -> &PsbObject {
207        &self.root
208    }
209
210    pub fn root_mut(&mut self) -> &mut PsbObject {
211        &mut self.root
212    }
213
214    pub fn set_root(&mut self, root: PsbObject) {
215        self.root = root;
216    }
217
218    pub fn unwrap(self) -> (PsbHeader, Vec<Vec<u8>>, Vec<Vec<u8>>, PsbObject) {
219        (
220            self.header,
221            self.resources,
222            self.extra,
223            self.root
224        )
225    }
226
227}
228
229#[derive(Debug)]
230pub struct PsbFile<T: Read + Seek> {
231
232    header: PsbHeader,
233    
234    refs: PsbRefs,
235    offsets: PsbOffsets,
236
237    stream: T
238
239}
240
241impl<T: Read + Seek> PsbFile<T> {
242
243    pub fn new(header: PsbHeader, refs: PsbRefs, offsets: PsbOffsets, stream: T) -> Self {
244        Self {
245            header,
246            refs,
247            offsets,
248            stream
249        }
250    }
251
252    pub fn header(&self) -> PsbHeader {
253        self.header
254    }
255
256    pub fn refs(&self) -> &PsbRefs {
257        &self.refs
258    }
259
260    pub fn offsets(&self) -> PsbOffsets {
261        self.offsets
262    }
263
264    pub fn entry_point(&self) -> u32 {
265        self.offsets.entry_point as u32
266    }
267
268    pub fn load_root(&mut self) -> Result<PsbObject, PsbError> {
269        self.stream.seek(SeekFrom::Start(self.entry_point() as u64))?;
270        let (_, root) = PsbValue::from_bytes_refs(&mut self.stream, &self.refs)?;
271
272        if let PsbValue::Object(root_obj) = root {
273            Ok(root_obj)
274        } else {
275            Err(PsbError::new(PsbErrorKind::InvalidPSBRoot, None))
276        }
277    }
278
279    pub fn load_resources(&mut self) -> Result<Vec<Vec<u8>>, PsbError> {
280        Self::load_from_table(&mut self.stream, self.offsets.resources)
281    }
282
283    pub fn load_extra(&mut self) -> Result<Vec<Vec<u8>>, PsbError> {
284        if self.offsets.extra.is_none() {
285            Ok(Vec::new())
286        } else {
287            Self::load_from_table(&mut self.stream, self.offsets.extra.unwrap())
288        }
289    }
290
291    fn load_from_table<R: Read + Seek>(stream: &mut R, table: PsbResourcesOffset) -> Result<Vec<Vec<u8>>, PsbError> {
292        stream.seek(SeekFrom::Start(table.offset_pos as u64))?;
293        let (_, resource_offsets) = match PsbValue::from_bytes(stream)? {
294    
295            (read, PsbValue::IntArray(array)) => Ok((read, array)),
296
297            _ => Err(PsbError::new(PsbErrorKind::InvalidOffsetTable, None))
298
299        }?;
300        
301        stream.seek(SeekFrom::Start(table.lengths_pos as u64))?;
302        let (_, resource_lengths) = match PsbValue::from_bytes(stream)? {
303
304            (read, PsbValue::IntArray(array)) => Ok((read, array)),
305
306            _ => Err(PsbError::new(PsbErrorKind::InvalidOffsetTable, None))
307
308        }?;
309
310        if resource_offsets.len() < resource_lengths.len() {
311            return Err(PsbError::new(PsbErrorKind::InvalidOffsetTable, None));
312        }
313
314        let mut resources = Vec::new();
315
316        let resource_offsets = resource_offsets.unwrap();
317        let resource_lengths = resource_lengths.unwrap();
318
319        for i in 0..resource_offsets.len() {
320            let mut buffer = Vec::new();
321
322            stream.seek(SeekFrom::Start(table.data_pos as u64 + resource_offsets[i] as u64))?;
323            stream.take(resource_lengths[i] as u64).read_to_end(&mut buffer)?;
324
325            resources.push(buffer);
326        }
327
328        Ok(resources)
329    }
330
331    /// Load Psb file to memory.
332    /// Returns VirtualPsb.
333    pub fn load(&mut self) -> Result<VirtualPsb, PsbError> {
334        let root = self.load_root()?;
335        let res = self.load_resources()?;
336        let extra = self.load_extra()?;
337
338        Ok(VirtualPsb::new(self.header, res, extra, root))
339    }
340
341    /// Unwrap stream
342    pub fn unwrap(self) -> T {
343        self.stream
344    }
345
346}