parseSessionLines function

Future<List<SessionRecord?>> parseSessionLines(
  1. List<String> lines, {
  2. required String filePath,
  3. required int firstLineNumber,
  4. SessionParseExecutor? executor,
  5. bool shallowGiantCustoms = false,
})

Parses lines through executor — or inline, batch by batch, when it is null — and returns one slot per line in file order (null where a line was torn/foreign).

Inline (web degradation): one await per batch — the event loop breathes between batches by construction.

Executor path: batches are independent, so they fan out with bounded concurrency — a marathon session walk parses a strip core-wide instead of one 4MB batch at a time (issue #503 boot cost: the sequential await serialized ~2.2s of jsonDecode on a 434MB tail). Results concatenate in batch order, so the returned list is byte-identical to the sequential walk.

Implementation

Future<List<SessionRecord?>> parseSessionLines(
  List<String> lines, {
  required String filePath,
  required int firstLineNumber,
  SessionParseExecutor? executor,
  bool shallowGiantCustoms = false,
}) async {
  if (lines.isEmpty) return const <SessionRecord?>[];
  final batches = splitSessionParseBatches(
    lines,
    filePath: filePath,
    firstLineNumber: firstLineNumber,
    shallowGiantCustoms: shallowGiantCustoms,
  );
  if (executor == null) {
    final records = <SessionRecord?>[];
    for (final batch in batches) {
      records.addAll(parseSessionEntryLinesSync(batch).records);
    }
    return records;
  }
  final results = List<SessionParseResult?>.filled(batches.length, null);
  var next = 0;
  Future<void> worker() async {
    while (next < batches.length) {
      final i = next++;
      results[i] = await executor.parse(batches[i]);
    }
  }

  await Future.wait([
    for (
      var w = 0;
      w < maxConcurrentSessionParseBatches && w < batches.length;
      w++
    )
      worker(),
  ]);
  return [for (final result in results) ...result!.records];
}