serializeParams function
Serializes a list of parameter values to binary format.
The params list should contain ParamValue instances in the order
they appear in the prepared statement.
Returns a Uint8List containing the serialized parameters.
Uses a two-pass strategy: phase 1 pre-encodes text payloads and computes the exact total byte count; phase 2 writes directly into a single pre-sized Uint8List — avoiding all intermediate list allocations and the final Uint8List.fromList copy that the old approach required.
Implementation
Uint8List serializeParams(List<ParamValue> params) {
if (params.isEmpty) return Uint8List(0);
// Phase 1: pre-encode text payloads and compute total byte size.
var totalBytes = 0;
final encodedText = List<List<int>?>.filled(params.length, null);
for (var i = 0; i < params.length; i++) {
switch (params[i]) {
case ParamValueNull():
totalBytes += 5;
case ParamValueString(:final value):
final b = utf8.encode(value);
encodedText[i] = b;
totalBytes += 5 + b.length;
case ParamValueInt32():
totalBytes += 9;
case ParamValueInt64():
totalBytes += 13;
case ParamValueDecimal(:final value):
final b = utf8.encode(value);
encodedText[i] = b;
totalBytes += 5 + b.length;
case ParamValueBinary(:final value):
totalBytes += 5 + value.length;
case ParamValueRefCursorOut():
totalBytes += 5;
}
}
// Phase 2: write all params into the pre-sized buffer.
final out = Uint8List(totalBytes);
final bd = ByteData.sublistView(out);
var off = 0;
for (var i = 0; i < params.length; i++) {
switch (params[i]) {
case ParamValueNull():
out[off] = _tagNull;
bd.setUint32(off + 1, 0, _littleEndian);
off += 5;
case ParamValueString():
final b = encodedText[i]!;
out[off] = _tagString;
bd.setUint32(off + 1, b.length, _littleEndian);
out.setRange(off + 5, off + 5 + b.length, b);
off += 5 + b.length;
case ParamValueInt32(:final value):
out[off] = _tagInteger;
bd.setUint32(off + 1, 4, _littleEndian);
bd.setInt32(off + 5, value, _littleEndian);
off += 9;
case ParamValueInt64(:final value):
out[off] = _tagBigInt;
bd.setUint32(off + 1, 8, _littleEndian);
bd.setInt64(off + 5, value, _littleEndian);
off += 13;
case ParamValueDecimal():
final b = encodedText[i]!;
out[off] = _tagDecimal;
bd.setUint32(off + 1, b.length, _littleEndian);
out.setRange(off + 5, off + 5 + b.length, b);
off += 5 + b.length;
case ParamValueBinary(:final value):
final vLen = value.length;
out[off] = _tagBinary;
bd.setUint32(off + 1, vLen, _littleEndian);
out.setRange(off + 5, off + 5 + vLen, value);
off += 5 + vLen;
case ParamValueRefCursorOut():
out[off] = _tagRefCursorOut;
bd.setUint32(off + 1, 0, _littleEndian);
off += 5;
}
}
return out;
}