decodeRemotePlan function

RemotePlan decodeRemotePlan(
  1. Uint8List bytes
)

Decodes a RemotePlan from wire bytes.

Implementation

RemotePlan decodeRemotePlan(Uint8List bytes) {
  final r = _Reader(bytes);
  final flags = r.u8();
  if (flags & ~3 != 0) {
    throw RemoteCodecException(
      'unknown plan flags 0x${flags.toRadixString(16)}',
    );
  }
  final cols = r.varint();
  final rows = r.varint();
  _validatePlanGrid(cols, rows);
  final scrollUp = (flags & 2) != 0 ? r.varint() : null;
  if (scrollUp != null && (scrollUp <= 0 || scrollUp >= rows)) {
    throw RemoteCodecException(
      'scroll row count $scrollUp is outside 1..${rows - 1}',
    );
  }
  final styleCount = r.varint();
  _checkPlanCount('style', styleCount, maxRemotePlanStyles);
  final styleTable = <CellStyle>[
    for (var i = 0; i < styleCount; i++) _readStyle(r),
  ];
  final patchCount = r.varint();
  _checkPlanCount('patch', patchCount, maxRemotePlanPatches);
  final patches = <RemoteRowPatch>[];
  var totalRuns = 0;
  for (var i = 0; i < patchCount; i++) {
    final row = r.varint();
    final startCol = r.varint();
    if (row >= rows || startCol >= cols) {
      throw RemoteCodecException(
        'patch $i starts outside ${cols}x$rows grid: col=$startCol,row=$row',
      );
    }
    final runCount = r.varint();
    _checkPlanCount('patch run', runCount, cols);
    if (runCount == 0) {
      throw RemoteCodecException('patch $i has no runs');
    }
    totalRuns += runCount;
    _checkPlanCount('total run', totalRuns, maxRemotePlanRuns);
    final runs = <RemotePatchRun>[];
    for (var j = 0; j < runCount; j++) {
      final styleIndex = r.varint();
      if (styleIndex >= styleTable.length) {
        throw RemoteCodecException('style index $styleIndex out of range');
      }
      final text = r.vstr();
      if (text.isEmpty) {
        throw RemoteCodecException('patch $i run $j has empty text');
      }
      runs.add(RemotePatchRun(styleIndex: styleIndex, text: text));
    }
    patches.add(
      RemoteRowPatch(
        row: row,
        startCol: startCol,
        runs: List.unmodifiable(runs),
      ),
    );
  }
  final placementCount = r.varint();
  _checkPlanCount('image placement', placementCount, maxRemotePlanPlacements);
  final placements = <ImagePlacement>[];
  for (var i = 0; i < placementCount; i++) {
    final id = r.vstr();
    final prow = r.varint();
    final pcol = r.varint();
    final pcols = r.varint();
    final prows = r.varint();
    final fitIndex = r.varint();
    final boxCols = r.varint();
    final boxRows = r.varint();
    final boxOffsetCol = r.varint();
    final boxOffsetRow = r.varint();
    if (id.isEmpty || id.length > 256) {
      throw RemoteCodecException(
        'image placement $i id length is outside 1..256',
      );
    }
    if (pcols <= 0 ||
        prows <= 0 ||
        pcols > maxRemotePlanGridCols ||
        prows > maxRemotePlanGridRows ||
        pcol >= cols ||
        prow >= rows ||
        pcol + pcols > cols ||
        prow + prows > rows) {
      throw RemoteCodecException(
        'image placement $i is outside ${cols}x$rows grid',
      );
    }
    if (boxCols <= 0 ||
        boxRows <= 0 ||
        boxCols > maxRemotePlanGridCols ||
        boxRows > maxRemotePlanGridRows ||
        boxOffsetCol + pcols > boxCols ||
        boxOffsetRow + prows > boxRows) {
      throw RemoteCodecException(
        'image placement $i visible window is outside its '
        '${boxCols}x$boxRows source box',
      );
    }
    if (fitIndex >= InlineImageFit.values.length) {
      throw RemoteCodecException(
        'image placement $i has unknown fit $fitIndex',
      );
    }
    final fit = InlineImageFit.values[fitIndex];
    placements.add(
      ImagePlacement(
        id: id,
        col: pcol,
        row: prow,
        cols: pcols,
        rows: prows,
        fit: fit,
        boxCols: boxCols,
        boxRows: boxRows,
        boxOffsetCol: boxOffsetCol,
        boxOffsetRow: boxOffsetRow,
      ),
    );
  }
  r.expectEnd();
  return RemotePlan(
    size: CellSize(cols, rows),
    fullRepaint: (flags & 1) != 0,
    scrollUpRows: scrollUp,
    styleTable: List.unmodifiable(styleTable),
    patches: List.unmodifiable(patches),
    placements: List.unmodifiable(placements),
  );
}