1use std::io::{BufRead, BufReader, Cursor, Read, Seek, SeekFrom};
8
9use byteorder::{ReadBytesExt, LittleEndian};
10use encoding::{Encoding, all::UTF_8};
11use flate2::read::ZlibDecoder;
12
13use crate::{PSB_MDF_SIGNATURE, PSB_SIGNATURE, PsbError, PsbErrorKind, PsbFile, PsbRefs, header::{MdfHeader, PsbHeader}, offsets::PsbOffsets, types::{PsbValue, binary_tree::PsbBinaryTree}};
14
15pub struct PsbReader;
16
17impl PsbReader {
18
19 pub fn open_psb<T: Read + Seek>(mut stream: T) -> Result<PsbFile<T>, PsbError> {
21 let start = stream.seek(SeekFrom::Current(0)).unwrap();
22
23 let signature = stream.read_u32::<LittleEndian>()?;
24 if signature != PSB_SIGNATURE {
25 return Err(PsbError::new(PsbErrorKind::InvalidFile, None));
26 }
27
28 let (_, header) = PsbHeader::from_bytes(&mut stream)?;
29
30 let _ = stream.read_u32::<LittleEndian>()?;
31
32 let (_, offsets) = PsbOffsets::from_bytes(header.version, &mut stream)?;
34
35 stream.seek(SeekFrom::Start(start + offsets.name_offset as u64))?;
36 let (_, names) = Self::read_names(&mut stream)?;
37
38 stream.seek(SeekFrom::Start(start + offsets.strings.offset_pos as u64))?;
39 let (_, strings) = Self::read_strings(offsets.strings.data_pos + start as u32, &mut stream)?;
40
41 let refs = PsbRefs::new(names, strings);
42
43 Ok(
44 PsbFile::new(
45 header,
46 refs,
47 offsets,
48 stream
49 )
50 )
51 }
52
53 pub fn read_names<T: Read + Seek>(stream: &mut T) -> Result<(u64, Vec<String>), PsbError> {
54 let mut names = Vec::<String>::new();
55
56 let (read, btree) = PsbBinaryTree::from_bytes(stream)?;
57
58 for raw_string in btree.unwrap() {
59 let name = UTF_8.decode(&raw_string, encoding::DecoderTrap::Replace).unwrap();
60
61 names.push(name);
62 }
63
64 Ok((read, names))
65 }
66
67 pub fn read_strings<T: Read + Seek>(data_pos: u32, stream: &mut T) -> Result<(u64, Vec<String>), PsbError> {
68 let mut strings = Vec::<String>::new();
69
70 let (offsets_read, string_offsets) = match PsbValue::from_bytes(stream)? {
71
72 (read, PsbValue::IntArray(array)) => Ok((read, array)),
73
74 _ => Err(PsbError::new(PsbErrorKind::InvalidOffsetTable, None))
75
76 }?;
77
78 let mut reader = BufReader::new(stream.by_ref());
79 let string_offsets = string_offsets.unwrap();
80
81 let mut read = 0_usize;
82 for offset in string_offsets {
83 let mut buffer = Vec::new();
84
85 reader.seek(SeekFrom::Start(data_pos as u64 + offset as u64))?;
86 read += reader.read_until(0x00, &mut buffer)?;
87
88 let string = UTF_8.decode(&buffer[..buffer.len() - 1], encoding::DecoderTrap::Replace).unwrap();
90 strings.push(string);
91 }
92
93 Ok((offsets_read + read as u64, strings))
94 }
95
96}
97
98pub struct MdfReader;
99
100impl MdfReader {
101
102 pub fn open_mdf<T: Read + Seek>(mut stream: T) -> Result<PsbFile<Cursor<Vec<u8>>>, PsbError> {
103 let signature = stream.read_u32::<LittleEndian>()?;
104 if signature != PSB_MDF_SIGNATURE {
105 return Err(PsbError::new(PsbErrorKind::InvalidFile, None));
106 }
107
108 let (_, mdf_header) = MdfHeader::from_bytes(&mut stream)?;
109
110 let mut compressed_buffer = Vec::new();
111
112 stream.take(mdf_header.size as u64).read_to_end(&mut compressed_buffer)?;
113
114 let mut decoder = ZlibDecoder::new(&compressed_buffer[..]);
115
116 let mut buffer = Vec::new();
117 decoder.read_to_end(&mut buffer)?;
118
119 PsbReader::open_psb(Cursor::new(buffer))
120 }
121
122}