encodeMetadata static method
Uint8List
encodeMetadata({
- required int streamId,
- required RpcMetadata metadata,
- 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;
}