marshalRepeated function
Marshals a repeated scalar field using packed encoding and appends it to
buffer.
Packed encoding writes a single tag + length prefix, then concatenates all the scalar values without individual tags.
For non-packable types (string, bytes, message) this is a no-op — those are handled by the caller with individual field entries.
Returns buffer with the packed field bytes appended.
Implementation
List<int> marshalRepeated(
List<int> buffer,
int fieldNumber,
String type,
List<Object?> values,
) {
if (values.isEmpty) return buffer;
switch (type) {
// Varint-encoded packed types.
case 'TYPE_INT32':
case 'TYPE_INT64':
case 'TYPE_UINT32':
case 'TYPE_UINT64':
final ints = values.map(_toInt).toList();
encodePackedVarintsField(buffer, fieldNumber, ints);
case 'TYPE_SINT32':
final temp = <int>[];
for (final v in values) {
encodeVarint(temp, encodeZigZag32(_toInt(v)));
}
encodeTag(buffer, fieldNumber, _wtLen);
encodeBytes(buffer, temp);
case 'TYPE_SINT64':
final temp = <int>[];
for (final v in values) {
encodeVarint(temp, encodeZigZag64(_toInt(v)));
}
encodeTag(buffer, fieldNumber, _wtLen);
encodeBytes(buffer, temp);
case 'TYPE_BOOL':
final ints = values.map((v) => (v as bool) ? 1 : 0).toList();
encodePackedVarintsField(buffer, fieldNumber, ints);
case 'TYPE_ENUM':
final ints = values.map(_toInt).toList();
encodePackedVarintsField(buffer, fieldNumber, ints);
// Fixed-width packed types.
case 'TYPE_FIXED32':
case 'TYPE_SFIXED32':
final ints = values.map(_toInt).toList();
encodePackedFixed32Field(buffer, fieldNumber, ints);
case 'TYPE_FLOAT':
final temp = <int>[];
for (final v in values) {
temp.addAll(_encodeFloatBytes(_toDouble(v)));
}
encodeTag(buffer, fieldNumber, _wtLen);
encodeBytes(buffer, temp);
case 'TYPE_FIXED64':
case 'TYPE_SFIXED64':
final ints = values.map(_toInt).toList();
encodePackedFixed64Field(buffer, fieldNumber, ints);
case 'TYPE_DOUBLE':
final temp = <int>[];
for (final v in values) {
temp.addAll(_encodeDoubleBytes(_toDouble(v)));
}
encodeTag(buffer, fieldNumber, _wtLen);
encodeBytes(buffer, temp);
// Non-packable types — encode each element as a separate field.
case 'TYPE_STRING':
for (final v in values) {
if (v == null) continue;
encodeStringField(buffer, fieldNumber, v as String);
}
case 'TYPE_BYTES':
for (final v in values) {
if (v == null) continue;
encodeBytesField(buffer, fieldNumber, v as List<int>);
}
case 'TYPE_MESSAGE':
for (final v in values) {
if (v == null) continue;
encodeMessageField(buffer, fieldNumber, v as List<int>);
}
default:
throw ArgumentError(
'Unknown protobuf field type for packed encoding: $type',
);
}
return buffer;
}