1use crate::FILEFLAGS_DEFAULT;
2use crate::FILEFLAGS_END;
3use crate::MAGIC;
4use crate::PakError;
5use crate::VERSION;
6use crate::entry::Entry;
7use crate::reader::PakReader;
8use crate::writer::PakWriter;
9use std::io::Cursor;
10use std::io::Read;
11use std::io::Write;
12
13#[derive(Debug, PartialEq)]
17pub struct Pak<'a> {
18 pub entries: Vec<Entry<'a>>,
22}
23
24impl<'a> Pak<'a> {
25 pub fn new() -> Self {
27 Self {
28 entries: Vec::new(),
29 }
30 }
31
32 pub fn from_read<R>(reader: R) -> Result<Pak<'static>, PakError>
40 where
41 R: Read,
42 {
43 let mut reader = PakReader::new(reader);
44 reader.read_magic()?;
45 reader.read_version()?;
46
47 let records = reader.read_records()?;
48
49 let mut entries = Vec::with_capacity(records.len());
50 for record in records {
51 let mut data = vec![
52 0;
53 usize::try_from(record.file_size).map_err(|error| {
54 PakError::InvalidRecordFileSize {
55 file_size: record.file_size,
56 error,
57 }
58 })?
59 ];
60 reader.read_exact(&mut data)?;
61
62 entries.push(Entry {
63 path: record.name.into(),
64 file_time: record.file_time,
65 data: Cursor::new(data.into()),
66 });
67 }
68
69 Ok(Pak { entries })
70 }
71
72 pub fn from_bytes(bytes: &'a [u8]) -> Result<Pak<'a>, PakError> {
81 let mut reader = PakReader::new(bytes);
82 reader.read_magic()?;
83 reader.read_version()?;
84
85 let records = reader.read_records()?;
86
87 let mut bytes = reader.into_reader();
88
89 let mut entries = Vec::with_capacity(records.len());
90 for record in records {
91 let len = usize::try_from(record.file_size).map_err(|error| {
92 PakError::InvalidRecordFileSize {
93 file_size: record.file_size,
94 error,
95 }
96 })?;
97 let data = &bytes[..len];
98 bytes = &bytes[len..];
99
100 entries.push(Entry {
101 path: record.name.into(),
102 file_time: record.file_time,
103 data: Cursor::new(data.into()),
104 });
105 }
106
107 Ok(Self { entries })
108 }
109
110 pub fn into_owned(self) -> Pak<'static> {
113 let entries = self
114 .entries
115 .into_iter()
116 .map(|entry| entry.into_owned())
117 .collect();
118
119 Pak { entries }
120 }
121
122 pub fn write_to<W>(&mut self, writer: W) -> Result<(), PakError>
127 where
128 W: Write,
129 {
130 let mut writer = PakWriter::new(writer);
131 writer.write_all(MAGIC)?;
132 writer.write_all(VERSION)?;
133
134 for entry in self.entries.iter() {
135 writer.write_u8(FILEFLAGS_DEFAULT)?;
136 writer.write_filename(&entry.path)?;
137 writer.write_u32(entry.size().try_into().map_err(|error| {
138 PakError::InvalidFileDataLength {
139 length: entry.size(),
140 error,
141 }
142 })?)?;
143 writer.write_u64(entry.file_time.into_raw())?;
144 }
145 writer.write_u8(FILEFLAGS_END)?;
146
147 for entry in self.entries.iter_mut() {
148 std::io::copy(entry, &mut writer)?;
149 }
150
151 Ok(())
152 }
153}
154
155impl<'a> Default for Pak<'a> {
156 fn default() -> Self {
157 Self::new()
158 }
159}