encodeMetadata static method

Uint8List encodeMetadata({
  1. required int streamId,
  2. required RpcMetadata metadata,
  3. bool endOfStream = false,
})

Encode a metadata frame (headers + optional methodPath).

Implementation

static Uint8List encodeMetadata({
  required int streamId,
  required RpcMetadata metadata,
  bool endOfStream = false,
}) {
  int flags = flagMetadata;
  if (endOfStream) flags |= _flagEndOfStream;

  // Two passes over the strings, one buffer: sizes first, then the bytes
  // straight into the frame. A string outside ASCII is encoded once, in the
  // first pass, and kept for the second.
  final path = metadata.methodPath;
  final headers = metadata.headers;
  final strings = <String>[?path];
  for (final h in headers) {
    strings
      ..add(h.name)
      ..add(h.value);
  }
  final encoded = List<Uint8List?>.filled(strings.length, null);
  var payloadLen = 0;
  for (var i = 0; i < strings.length; i++) {
    final s = strings[i];
    var len = s.length;
    if (!_isAscii(s)) {
      final bytes = utf8.encode(s);
      encoded[i] = bytes;
      len = bytes.length;
    }
    payloadLen += len + _varintSize(len);
  }
  if (path == null) payloadLen += 1;
  payloadLen += _varintSize(headers.length);

  final frame = Uint8List(headerSize + payloadLen);
  final view = ByteData.sublistView(frame);
  view.setUint32(0, streamId);
  view.setUint8(4, flags);
  view.setUint32(5, payloadLen);

  var o = headerSize;
  var i = 0;
  if (path == null) {
    frame[o++] = 0;
  } else {
    o = _writeString(frame, o, path, encoded[i++], plusOne: true);
  }
  o = _writeVarint(frame, o, headers.length);
  for (; i < strings.length; i++) {
    o = _writeString(frame, o, strings[i], encoded[i]);
  }
  return frame;
}