extractEntry method

  1. @override
Future<List<int>> extractEntry({
  1. required RarArchiveEntry entry,
})
override

Extracts the content of the specified entry from the RAR archive.

Returns a list of bytes representing the unpacked content of the entry. Throws a RarException if the extraction fails or the entry is compressed using an unsupported compression method.

Implementation

@override
Future<List<int>> extractEntry({required RarArchiveEntry entry}) async {
  if (entry.isDirectory) {
    return const [];
  }

  if (entry.compressionMethod != 0 && entry.compressionMethod != 0x33) {
    final err =
        'Unsupported compression method: 0x${entry.compressionMethod.toRadixString(16)}. '
        'Only stored (uncompressed) entries and RAR4 normal (0x33) compression are supported.';
    stderr.writeln(err);
    throw RarException(err);
  }

  try {
    final raf = await _file.open(mode: FileMode.read);
    try {
      await raf.setPosition(entry.dataOffset);
      final data = await raf.read(entry.packedSize);
      if (data.length < entry.packedSize) {
        throw RarException(
          'Truncated file data for "${entry.name}": Read ${data.length} bytes, expected ${entry.packedSize}.',
        );
      }

      if (entry.compressionMethod == 0x33) {
        final bstream = _RarBitStream(data);
        final decompressor = _Rar4Decompressor();
        return decompressor.decompress(bstream, entry.size);
      } else {
        return data;
      }
    } finally {
      await raf.close();
    }
  } catch (e, stackTrace) {
    stderr.writeln(
        'Error extracting RAR entry "${entry.name}": $e\n$stackTrace');
    if (e is RarException) {
      rethrow;
    }
    throw RarException('Failed to extract RAR entry "${entry.name}"', e);
  }
}