marshalRepeated function

List<int> marshalRepeated(
  1. List<int> buffer,
  2. int fieldNumber,
  3. String type,
  4. List<Object?> values,
)

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;
}