arsc/parser/
components_read.rs

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)?; // string length
72        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))?; // skip null terminator
101        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}