ArchiveReader.decode constructor
ArchiveReader.decode(
- Uint8List bytes,
- ArchiveFormat format
Decodes bytes as format into an indexed reader. Throws StateError
when the archive exceeds maxArchiveBytes or fails to decode.
Implementation
factory ArchiveReader.decode(Uint8List bytes, ArchiveFormat format) {
if (bytes.length > maxArchiveBytes) {
throw StateError(
'Archive is too large to read in memory '
'(${bytes.length} bytes > $maxArchiveBytes byte limit)',
);
}
// ZipDecoder is lenient with garbage input (it yields an empty archive);
// every real ZIP — even an empty one — starts with a PK record
// signature, so reject non-ZIP bytes up front (omp's framing rejects a
// missing end-of-central-directory record the same way).
if (format == ArchiveFormat.zip &&
(bytes.length < 2 || bytes[0] != 0x50 || bytes[1] != 0x4B)) {
throw StateError('Cannot read archive: not a ZIP file');
}
final Archive decoded;
try {
decoded = switch (format) {
ArchiveFormat.zip => ZipDecoder().decodeBytes(bytes),
ArchiveFormat.tar => TarDecoder().decodeBytes(bytes),
ArchiveFormat.tarGz => TarDecoder().decodeBytes(
GZipDecoder().decodeBytes(bytes),
),
};
} on Object catch (error) {
throw StateError('Cannot read archive: $error');
}
final entries = <_IndexEntry>[];
for (final file in decoded.files) {
final normalizedPath = _normalizeArchiveEntryPath(file.name);
if (normalizedPath == null) continue;
final isDirectory =
!file.isFile || file.name.endsWith('/') || file.name.endsWith('\\');
entries.add(
_IndexEntry(
path: normalizedPath,
isDirectory: isDirectory,
size: isDirectory ? 0 : file.size,
file: isDirectory ? null : file,
),
);
}
return ArchiveReader._(format, entries);
}