parseBinaryColumnData function

(dynamic, int) parseBinaryColumnData(
  1. int columnType,
  2. ByteData data,
  3. Uint8List buffer,
  4. int startOffset, {
  5. bool unsigned = false,
})

Função auxiliar para analisar dados de coluna em formato binário.

columnType: O tipo da coluna (valor inteiro representando o tipo MySQL). data: Um ByteData que fornece acesso aos bytes do buffer. buffer: O Uint8List original contendo os dados. startOffset: A posição inicial no buffer para leitura.

Retorna um record (dynamic, int) contendo:

  • $1: O valor lido da coluna (geralmente convertido para string ou, em casos binários, um Uint8List).
  • $2: O número de bytes consumidos durante a leitura.

Caso o tipo da coluna não seja implementado, lança MySQLProtocolException.

Implementation

(dynamic, int) parseBinaryColumnData(
  int columnType,
  ByteData data,
  Uint8List buffer,
  int startOffset, {
  bool unsigned = false,
}) {
  final limit =
      data.lengthInBytes < buffer.length ? data.lengthInBytes : buffer.length;
  if (startOffset < 0) {
    throw const MySQLProtocolException(
      'Invalid negative startOffset while parsing binary column data',
    );
  }

  // [unsigned] comes from the column's UNSIGNED flag: without it a
  // TINYINT UNSIGNED 200 was read as -56 (and so on for every width).
  switch (columnType) {
    case mysqlColumnTypeTiny:
      _requireBinaryBytes(startOffset, 1, limit);
      final value =
          unsigned ? data.getUint8(startOffset) : data.getInt8(startOffset);
      return (value.toString(), 1);

    case mysqlColumnTypeShort:
      _requireBinaryBytes(startOffset, 2, limit);
      final value = unsigned
          ? data.getUint16(startOffset, Endian.little)
          : data.getInt16(startOffset, Endian.little);
      return (value.toString(), 2);

    case mysqlColumnTypeLong:
    case mysqlColumnTypeInt24:
      _requireBinaryBytes(startOffset, 4, limit);
      final value = unsigned
          ? data.getUint32(startOffset, Endian.little)
          : data.getInt32(startOffset, Endian.little);
      return (value.toString(), 4);

    case mysqlColumnTypeLongLong:
      return _parseBinaryLongLong(data, startOffset, limit, unsigned);

    case mysqlColumnTypeFloat:
      _requireBinaryBytes(startOffset, 4, limit);
      final value = data.getFloat32(startOffset, Endian.little);
      return (value.toString(), 4);

    case mysqlColumnTypeDouble:
      _requireBinaryBytes(startOffset, 8, limit);
      final value = data.getFloat64(startOffset, Endian.little);
      return (value.toString(), 8);

    case mysqlColumnTypeDate:
    case mysqlColumnTypeDateTime:
    case mysqlColumnTypeTimestamp:
      return _parseBinaryDateTime(data, startOffset, limit);

    case mysqlColumnTypeTime:
    case mysqlColumnTypeTime2:
      return _parseBinaryTime(data, startOffset, limit);

    case mysqlColumnTypeString:
    case mysqlColumnTypeVarString:
    case mysqlColumnTypeVarChar:
    case mysqlColumnTypeEnum:
    case mysqlColumnTypeSet:
    case mysqlColumnTypeJson:
    case mysqlColumnTypeDecimal:
    case mysqlColumnTypeNewDecimal:
      final slice = readLengthEncodedSlice(
        buffer,
        startOffset,
        limit,
        allowNullMarker: false,
      );
      final strValue = utf8.decode(slice.bytes!, allowMalformed: true);
      return (strValue, slice.nextOffset - startOffset);

    case mysqlColumnTypeLongBlob:
    case mysqlColumnTypeMediumBlob:
    case mysqlColumnTypeBlob:
    case mysqlColumnTypeTinyBlob:
    case mysqlColumnTypeGeometry:
    case mysqlColumnTypeBit:
      final slice = readLengthEncodedSlice(
        buffer,
        startOffset,
        limit,
        allowNullMarker: false,
      );
      return (slice.bytes!, slice.nextOffset - startOffset);

    case mysqlColumnTypeYear:
      _requireBinaryBytes(startOffset, 2, limit);
      final yearValue = data.getUint16(startOffset, Endian.little);
      return (yearValue.toString(), 2);
  }

  throw MySQLProtocolException(
    "Can not parse binary column data: column type $columnType is not implemented",
  );
}