1use super::read_util;
2use crate::components::{Header, ResourceType, StringPool, Value};
3use crate::{
4 Arsc, Config, Package, ResourceEntry, ResourceValue, Resources, Spec, Specs, Style, StyleSpan,
5 Type,
6};
7use std::io::{BufReader, Error, Read, Seek, SeekFrom};
8
9impl<R: Read> TryFrom<&mut BufReader<R>> for Header {
10 type Error = std::io::Error;
11
12 fn try_from(reader: &mut BufReader<R>) -> Result<Self, Self::Error> {
13 let type_bits = read_util::read_u16(reader)?;
14 let r#type = ResourceType::from(type_bits);
15 let header_size = read_util::read_u16(reader)?;
16 let size = read_util::read_u32(reader)? as u64;
17 Ok(Header {
18 resource_type: r#type,
19 header_size,
20 size,
21 })
22 }
23}
24
25impl<R: Read + Seek> TryFrom<&mut BufReader<R>> for StringPool {
26 type Error = std::io::Error;
27
28 fn try_from(reader: &mut BufReader<R>) -> Result<Self, Self::Error> {
29 let base = reader.stream_position()?;
30 let header = crate::Header::try_from(&mut *reader)?;
31 assert_eq!(header.resource_type, crate::ResourceType::StringPool);
32
33 let string_count = read_util::read_u32(reader)? as usize;
34 let style_count = read_util::read_u32(reader)? as usize;
35 let flags = read_util::read_u32(reader)?;
36 let string_offset = read_util::read_u32(reader)? as u64;
37 let style_offset = read_util::read_u32(reader)? as u64;
38 let mut offsets = Vec::with_capacity(string_count);
39 for _ in 0..string_count {
40 offsets.push(read_util::read_u32(reader)? as u64)
41 }
42 let mut style_offsets = Vec::with_capacity(style_count);
43 for _ in 0..style_count {
44 style_offsets.push(read_util::read_u32(reader)? as u64)
45 }
46 debug_assert_eq!(reader.stream_position()?, string_offset + base);
47 let mut strings = Vec::with_capacity(string_count);
48 for _ in 0..string_count {
49 let string = if flags & StringPool::UTF8_FLAG != 0 {
50 StringPool::read_utf8_string_item(reader)?
51 } else {
52 StringPool::read_utf16_string_item(reader)?
53 };
54 strings.push(string);
55 }
56 reader.seek(SeekFrom::Start(base + style_offset))?;
57 let styles = std::iter::repeat_with(|| Style::try_from(&mut *reader))
58 .take(style_count)
59 .collect::<std::io::Result<Vec<_>>>()?;
60 reader.seek(SeekFrom::Start(base + header.size))?;
61 Ok(StringPool {
62 flags,
63 strings,
64 styles,
65 })
66 }
67}
68
69impl StringPool {
70 fn read_utf8_string_item<R: Read + Seek>(reader: &mut BufReader<R>) -> Result<String, Error> {
71 let _char_count = Self::utf8_length(reader)?; let byte_count = Self::utf8_length(reader)?;
73 let start = reader.stream_position()?;
74 let mut string_bytes = Vec::with_capacity(byte_count);
75 for _ in 0..byte_count {
76 let byte = read_util::read_u8(reader)?;
77 if byte == 0 {
78 break;
79 }
80 string_bytes.push(byte);
81 }
82 reader.seek(SeekFrom::Start(start + byte_count as u64 + 1))?;
83 Ok(String::from_utf8(string_bytes).expect("Not uft-8"))
84 }
85
86 fn utf8_length<R: Read>(reader: &mut BufReader<R>) -> Result<usize, Error> {
87 let mut length = read_util::read_u8(reader)? as usize;
88 if (length & 0x80) != 0 {
89 length = ((length & 0x7F) << 8) | read_util::read_u8(reader)? as usize;
90 }
91 Ok(length)
92 }
93
94 fn read_utf16_string_item<R: Read + Seek>(reader: &mut BufReader<R>) -> Result<String, Error> {
95 let char_count = Self::utf16_length(reader)?;
96 let mut string_bytes = Vec::with_capacity(char_count);
97 for _ in 0..char_count {
98 string_bytes.push(read_util::read_u16(reader)?);
99 }
100 reader.seek(SeekFrom::Current(2))?; Ok(String::from_utf16(&string_bytes).expect("Not utf-16"))
102 }
103
104 fn utf16_length<R: Read>(reader: &mut BufReader<R>) -> Result<usize, Error> {
105 let mut length = read_util::read_u16(reader)? as usize;
106 if length > 0x7FFF {
107 length = ((length & 0x7FFF) << 8) | read_util::read_u16(reader)? as usize;
108 }
109 Ok(length)
110 }
111}
112impl<R: Read + Seek> TryFrom<&mut BufReader<R>> for Style {
113 type Error = std::io::Error;
114
115 fn try_from(reader: &mut BufReader<R>) -> Result<Self, Self::Error> {
116 let mut spans = Vec::new();
117 loop {
118 let name = read_util::read_u32(reader)?;
119 if name == Style::RES_STRING_POOL_SPAN_END {
120 break;
121 }
122 let start = read_util::read_u32(reader)?;
123 let end = read_util::read_u32(reader)?;
124 spans.push(StyleSpan { name, start, end })
125 }
126 Ok(Style { spans })
127 }
128}
129
130impl<R: Read + Seek> TryFrom<&mut BufReader<R>> for Value {
131 type Error = std::io::Error;
132
133 fn try_from(reader: &mut BufReader<R>) -> Result<Self, Self::Error> {
134 let size = read_util::read_u16(reader)?;
135 let zero = read_util::read_u8(reader)?;
136 let r#type = read_util::read_u8(reader)?;
137 let data_index = read_util::read_u32(reader)? as usize;
138 Ok(Value {
139 size,
140 zero,
141 r#type,
142 data_index,
143 })
144 }
145}
146
147impl<R: Read + Seek> TryFrom<&mut BufReader<R>> for Specs {
148 type Error = std::io::Error;
149
150 fn try_from(reader: &mut BufReader<R>) -> Result<Self, Self::Error> {
151 let type_id = read_util::read_u8(reader)? as usize;
152 let res0 = read_util::read_u8(reader)?;
153 let res1 = read_util::read_u16(reader)?;
154 let entry_count = read_util::read_u32(reader)? as usize;
155
156 let specs = std::iter::repeat_with(|| read_util::read_u32(reader))
157 .take(entry_count)
158 .enumerate()
159 .map(|(id, flags)| Result::Ok(Spec::new(flags?, id)))
160 .collect::<Result<Vec<_>, Self::Error>>()?;
161 debug_assert!(!specs.is_empty(), "Specs cannot be empty");
162 Ok(Specs {
163 type_id,
164 res0,
165 res1,
166 specs,
167 header_size: u16::MAX,
168 })
169 }
170}
171
172impl<R: Read + Seek> TryFrom<&mut BufReader<R>> for ResourceEntry {
173 type Error = std::io::Error;
174
175 fn try_from(reader: &mut BufReader<R>) -> Result<Self, Self::Error> {
176 let _size = read_util::read_u16(reader)?;
177 let flags = read_util::read_u16(reader)?;
178 let name_index = read_util::read_u32(reader)? as usize;
179
180 let value = if flags & ResourceEntry::ENTRY_FLAG_COMPLEX != 0 {
181 let parent = read_util::read_u32(reader)?;
182 let count = read_util::read_u32(reader)? as usize;
183 let mut values = Vec::with_capacity(count);
184 for _ in 0..count {
185 let index = read_util::read_u32(reader)?;
186 let value = Value::try_from(&mut *reader)?;
187 values.push((index, value));
188 }
189 ResourceValue::Bag { parent, values }
190 } else {
191 ResourceValue::Plain(Value::try_from(reader)?)
192 };
193 Ok(ResourceEntry {
194 flags,
195 name_index,
196 value,
197 spec_id: usize::MAX,
198 })
199 }
200}
201
202impl<R: Read + Seek> TryFrom<&mut BufReader<R>> for Config {
203 type Error = std::io::Error;
204
205 fn try_from(reader: &mut BufReader<R>) -> Result<Self, Self::Error> {
206 let type_id = read_util::read_u8(reader)? as usize;
207 let res0 = read_util::read_u8(reader)?;
208 let res1 = read_util::read_u16(reader)?;
209 let entry_count = read_util::read_u32(reader)? as usize;
210 let _entry_start = read_util::read_u32(reader)?;
211 let config_id = Config::parse_config_id(reader)?;
212
213 let resources = Config::parse_config_resources(reader, entry_count)?;
214 Ok(Config {
215 type_id,
216 res0,
217 res1,
218 id: config_id,
219 resources,
220 header_size: u16::MAX,
221 })
222 }
223}
224
225impl Config {
226 fn parse_config_id<R: Read + Seek>(reader: &mut R) -> std::io::Result<Vec<u8>> {
227 let size = read_util::read_u32(reader)? as usize;
228 let mut config_id = vec![0_u8; size];
229 reader.seek(SeekFrom::Current(-4))?;
230 reader.read_exact(&mut config_id)?;
231 Ok(config_id)
232 }
233
234 fn parse_config_resources<R: Read + Seek>(
235 reader: &mut BufReader<R>,
236 entry_count: usize,
237 ) -> std::io::Result<Resources> {
238 let _current = reader.stream_position()?;
239 let entries = std::iter::repeat_with(|| read_util::read_u32(reader))
240 .take(entry_count)
241 .collect::<std::io::Result<Vec<_>>>()?;
242 let _current = reader.stream_position()?;
243 let mut resources = Vec::with_capacity(entry_count);
244 for (spec_index, entry) in entries.into_iter().enumerate() {
245 if entry == u32::MAX {
246 continue;
247 }
248 let mut resource = ResourceEntry::try_from(&mut *reader)?;
249 resource.spec_id = spec_index;
250 resources.push(resource);
251 }
252 resources.shrink_to_fit();
253 let resource_count = resources.len();
254 Ok(Resources {
255 resources,
256 missing_entries: entry_count - resource_count,
257 })
258 }
259}
260
261impl<R: Read + Seek> TryFrom<&mut BufReader<R>> for Package {
262 type Error = std::io::Error;
263
264 fn try_from(reader: &mut BufReader<R>) -> Result<Self, Self::Error> {
265 let package_header = Header::try_from(&mut *reader)?;
266 debug_assert_eq!(package_header.resource_type, ResourceType::TablePackage);
267 let package_id = read_util::read_u32(reader)?;
268 let package_name = Self::parse_package_name(reader)?;
269
270 let _type_string_offset = read_util::read_u32(reader)?;
271 let last_public_type = read_util::read_u32(reader)?;
272 let _key_string_offset = read_util::read_u32(reader)?;
273 let last_public_key = read_util::read_u32(reader)?;
274 let _type_id_offset = read_util::read_u32(reader)?;
275
276 let type_names = StringPool::try_from(&mut *reader)?;
277 let mut types = (1..=type_names.strings.len())
278 .map(Type::with_id)
279 .collect::<Vec<_>>();
280 let key_names = StringPool::try_from(&mut *reader)?;
281
282 while let Ok(header) = Header::try_from(&mut *reader) {
283 match header.resource_type {
284 ResourceType::TableTypeSpec => {
285 let mut specs = Specs::try_from(&mut *reader)?;
286 specs.header_size = header.header_size;
287 debug_assert!(
288 &types[specs.type_id - 1].specs.is_none(),
289 "Target type already has specs"
290 );
291 types[specs.type_id - 1].specs.replace(specs);
292 }
293 ResourceType::TableType => {
294 let mut config = Config::try_from(&mut *reader)?;
295 config.header_size = header.header_size;
296 types[config.type_id - 1].configs.push(config);
297 }
298 flag => unreachable!("Unexpected flag: {flag:?}"),
299 }
300 }
301 Ok(Package {
302 id: package_id,
303 name: package_name,
304 type_names,
305 last_public_type,
306 types,
307 key_names,
308 last_public_key,
309 })
310 }
311}
312
313impl Package {
314 fn parse_package_name<R: Read + Seek>(reader: &mut R) -> std::io::Result<String> {
315 read_util::read_string_utf16::<128, R>(reader)
316 }
317}
318
319impl<R: Read + Seek> TryFrom<&mut BufReader<R>> for Arsc {
320 type Error = std::io::Error;
321
322 fn try_from(reader: &mut BufReader<R>) -> Result<Self, Self::Error> {
323 let _header = Header::try_from(&mut *reader)?;
324 let package_count = read_util::read_u32(reader)? as usize;
325 let global_string_pool = StringPool::try_from(&mut *reader)?;
326 let packages = std::iter::repeat_with(|| Package::try_from(&mut *reader))
327 .take(package_count)
328 .collect::<Result<Vec<_>, Self::Error>>()?;
329 Ok(Arsc {
330 global_string_pool,
331 packages,
332 })
333 }
334}