Read a file fully into memory
(&self, path: &str)
| 60 | let index = Self::parse_index(&mut cursor)?; |
| 61 | Ok(Self { data, index }) |
| 62 | } |
| 63 | |
| 64 | fn parse_index(cursor: &mut Cursor<&[u8]>) -> io::Result<HashMap<String, PerroAssetsEntry>> { |
| 65 | let header = read_header(cursor)?; |
| 66 | cursor.seek(SeekFrom::Start(header.index_offset))?; |
| 67 | let mut index = HashMap::new(); |
| 68 | |
| 69 | for _ in 0..header.file_count { |
| 70 | let (path, meta) = read_index_entry(cursor)?; |
| 71 | index.insert(path, meta); |
| 72 | } |
| 73 | |
| 74 | Ok(index) |
| 75 | } |
| 76 | |
| 77 | /// Read a file fully into memory |
| 78 | pub fn read_file(&self, path: &str) -> io::Result<Vec<u8>> { |
| 79 | let entry = self |
| 80 | .index |
| 81 | .get(path) |
| 82 | .ok_or_else(|| io::Error::new(io::ErrorKind::NotFound, "File not found"))?; |
| 83 | |
| 84 | let range = checked_entry_range(self.data.len(), entry)?; |
| 85 | let stored = &self.data[range]; |
| 86 | |
| 87 | // Decompress straight from the archive slice; only the uncompressed |
| 88 | // branch needs an owning copy. |
| 89 | if entry.flags & FLAG_COMPRESSED != 0 { |
| 90 | let expected_size = checked_decompressed_size(entry.original_size)?; |
| 91 | let decompressed = decompress_zlib_limited(stored, expected_size)?; |
| 92 | |
| 93 | if decompressed.len() as u64 != entry.original_size { |
no test coverage detected