decode static method

ExpressionBytecode decode(
  1. Uint8List bytes
)

The program bytes hold, verified.

Throws ExpressionBytecodeException for bytes that are not one, a version this build does not read, or a program verify refuses.

Implementation

static ExpressionBytecode decode(Uint8List bytes) {
  final data = ByteData.sublistView(bytes);
  var at = 0;
  void need(int count) {
    if (at + count > bytes.length) {
      throw const ExpressionBytecodeException('the bytes end early');
    }
  }

  int u16() {
    need(2);
    final v = data.getUint16(at, Endian.little);
    at += 2;
    return v;
  }

  need(4);
  for (final byte in expressionBytecodeMagic) {
    if (bytes[at++] != byte) {
      throw const ExpressionBytecodeException('not F3DX bytecode');
    }
  }
  final version = u16();
  // Every version up to this build's is read; only a newer one, or none,
  // is refused.
  if (version > expressionBytecodeVersion || version < 1) {
    throw ExpressionBytecodeException(
      'bytecode version $version; this build reads up to '
      '$expressionBytecodeVersion',
    );
  }
  u16();
  final lanes = u16();
  final constantCount = u16();
  final dimensionCount = u16();
  final inputCount = u16();
  final instructionCount = u16();
  final resultLane = u16();
  final resultWidth = u16();
  final resultDimension = u16();
  need(constantCount * 8);
  final constants = Float64List(constantCount);
  for (var i = 0; i < constantCount; i++) {
    constants[i] = data.getFloat64(at, Endian.little);
    at += 8;
  }
  // The exponents, then the byte that says a bool.
  final stride = _Dim.count + 1;
  need(dimensionCount * stride);
  final dimensions = <_Dim>[
    for (var i = 0; i < dimensionCount; i++)
      _Dim(<int>[
        for (var e = 0; e < _Dim.count; e++)
          data.getInt8(at + i * stride + e),
      ], data.getUint8(at + i * stride + _Dim.count) != 0),
  ];
  at += dimensionCount * stride;
  final inputs = <ExpressionBytecodeInput>[];
  for (var i = 0; i < inputCount; i++) {
    final length = u16();
    need(length);
    final name = utf8.decode(bytes.sublist(at, at + length));
    at += length;
    inputs.add(ExpressionBytecodeInput(name, u16(), u16(), u16()));
  }
  final code = Uint16List(instructionCount * 8);
  for (var i = 0; i < code.length; i++) {
    code[i] = u16();
  }
  if (at != bytes.length) {
    throw const ExpressionBytecodeException('bytes follow the program');
  }
  return ExpressionBytecode._(
    dimensions,
    lanes: lanes,
    constants: constants,
    inputs: inputs,
    code: code,
    resultLane: resultLane,
    resultWidth: resultWidth,
    resultDimension: resultDimension,
  )..verify();
}