59 lines
1.6 KiB
Dart
59 lines
1.6 KiB
Dart
import 'dart:convert';
|
|
|
|
/// Minimal reader retained only for endpoints that do not have an
|
|
/// authoritative generated protobuf model yet.
|
|
class ProtobufWireMessage {
|
|
ProtobufWireMessage(this.bytes);
|
|
|
|
final List<int> bytes;
|
|
Map<int, List<Object>>? _cache;
|
|
|
|
Map<int, List<Object>> get _fields => _cache ??= _read();
|
|
int integer(int tag) => (_fields[tag]?.lastOrNull as int?) ?? 0;
|
|
|
|
String string(int tag) {
|
|
final value = _fields[tag]?.lastOrNull;
|
|
return value is List<int> ? utf8.decode(value, allowMalformed: true) : '';
|
|
}
|
|
|
|
Map<int, List<Object>> _read() {
|
|
final result = <int, List<Object>>{};
|
|
var index = 0;
|
|
|
|
int varint() {
|
|
var value = 0;
|
|
var shift = 0;
|
|
while (index < bytes.length) {
|
|
final byte = bytes[index++];
|
|
value |= (byte & 127) << shift;
|
|
if (byte < 128) return value;
|
|
shift += 7;
|
|
}
|
|
throw const FormatException('Invalid protobuf');
|
|
}
|
|
|
|
while (index < bytes.length) {
|
|
final key = varint();
|
|
final tag = key >> 3;
|
|
final Object field;
|
|
if ((key & 7) == 0) {
|
|
field = varint();
|
|
} else if ((key & 7) == 2) {
|
|
final length = varint();
|
|
final end = index + length;
|
|
if (end > bytes.length) throw const FormatException('Invalid protobuf');
|
|
field = bytes.sublist(index, end);
|
|
index = end;
|
|
} else {
|
|
throw const FormatException('Unsupported protobuf');
|
|
}
|
|
(result[tag] ??= []).add(field);
|
|
}
|
|
return result;
|
|
}
|
|
}
|
|
|
|
extension on List<Object> {
|
|
Object? get lastOrNull => isEmpty ? null : last;
|
|
}
|