MySQLBinaryResultSetRowPacket.decode constructor
MySQLBinaryResultSetRowPacket.decode(
- Uint8List buffer,
- List<
MySQLColumnDefinitionPacket> colDefs, { - List<
bool> ? textualColumns,
Decodifica um pacote de linha de result set no modo binário.
buffer é o pacote recebido do servidor.
colDefs é a lista de definições de coluna que contém os tipos de cada coluna.
Retorna uma instância de MySQLBinaryResultSetRowPacket com os valores decodificados.
Lança MySQLProtocolException se o header do pacote não for 0x00.
Implementation
factory MySQLBinaryResultSetRowPacket.decode(
Uint8List buffer, List<MySQLColumnDefinitionPacket> colDefs,
{List<bool>? textualColumns}) {
final byteData = ByteData.sublistView(buffer);
int offset = 0;
// O primeiro byte do pacote deve ser 0x00 (header).
final type = byteData.getUint8(offset);
offset += 1;
if (type != 0) {
throw MySQLProtocolException(
"Cannot decode MySQLBinaryResultSetRowPacket: packet type is not 0x00",
);
}
// Inicializa a lista de valores (pode conter diferentes tipos).
final values = List<dynamic>.filled(colDefs.length, null, growable: false);
// Calcula o tamanho do null bitmap.
// O tamanho do bitmap é determinado por: ((numCols + 9) / 8).floor()
final nullBitmapSize = (colDefs.length + 9) >> 3;
final nullBitmapOffset = offset;
offset += nullBitmapSize;
// Itera sobre cada coluna para decodificar os dados.
for (int x = 0; x < colDefs.length; x++) {
// Determina qual byte e bit verificar no bitmap.
final bit = x + 2;
final bitmapByteIndex = bit >> 3;
final bitmapBitIndex = bit & 7;
final byteToCheck = buffer[nullBitmapOffset + bitmapByteIndex];
final isNull = (byteToCheck & (1 << bitmapBitIndex)) != 0;
if (isNull) {
// Já inicializado com null.
} else {
final colDef = colDefs[x];
final colType = colDef.type.intVal;
if (_isLengthEncodedBinaryColumnType(colType)) {
final packedLength = _readLengthEncodedHeader(buffer, offset);
final headerLength = packedLength & 0x0f;
final valueLength = packedLength >> 4;
final valueStart = offset + headerLength;
final valueEnd = valueStart + valueLength;
if (valueEnd > buffer.length) {
throw MySQLProtocolException(
"Cannot decode MySQLBinaryResultSetRowPacket: length-encoded column exceeds packet size",
);
}
final fieldBytes =
Uint8List.sublistView(buffer, valueStart, valueEnd);
offset = valueEnd;
values[x] = _shouldDecodeLengthEncodedColumnAsText(
colDef,
textualColumns?[x],
)
? utf8.decode(fieldBytes, allowMalformed: true)
: fieldBytes;
continue;
}
// Caso contrário, chama a função parseBinaryColumnData para ler o valor.
final parseResult = parseBinaryColumnData(
colType,
byteData,
buffer,
offset,
);
// Avança o offset de acordo com o número de bytes lidos.
offset += parseResult.item2;
var value = parseResult.item1;
if (value is Uint8List &&
(textualColumns?[x] ?? columnShouldBeTextual(colDefs[x]))) {
// Prepared statements also deliver textual blobs using the negotiated charset; decode accordingly.
value = utf8.decode(value, allowMalformed: true);
}
values[x] = value;
}
}
return MySQLBinaryResultSetRowPacket(
values: values,
);
}