pack static method

Future<int> pack({
  1. required RandomAccessFile sink,
  2. required List<PqPackEntry> entries,
  3. int chunkSize = 1 << 20,
})

Writes entries to sink sequentially. Returns the entry count.

Implementation

static Future<int> pack({
  required RandomAccessFile sink,
  required List<PqPackEntry> entries,
  int chunkSize = 1 << 20,
}) async {
  final buffer = Uint8List(chunkSize);
  for (final entry in entries) {
    _requireSafeRelativePath(entry.relativePath);
    final pathBytes = PqBytes.utf8Bytes(entry.relativePath);
    if (pathBytes.length > maxPathBytes) {
      throw PqForgeException(
        'Pack entry path too long: ${entry.relativePath}',
      );
    }
    final source = File(entry.sourcePath);
    final length = await source.length();
    final header =
        (BytesBuilder(copy: false)
              ..add(PqBytes.uint32(pathBytes.length))
              ..add(pathBytes)
              ..add(PqBytes.uint64(length)))
            .toBytes();
    await sink.writeFrom(header);
    final reader = await source.open();
    try {
      var remaining = length;
      while (remaining > 0) {
        final want = remaining < buffer.length ? remaining : buffer.length;
        final n = await reader.readInto(buffer, 0, want);
        if (n <= 0) {
          throw PqForgeException('Short read packing ${entry.relativePath}');
        }
        await sink.writeFrom(buffer, 0, n);
        remaining -= n;
      }
    } finally {
      await reader.close();
    }
  }
  return entries.length;
}