decodeRemotePlan function
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),
);
}