blob: 463b22b5bb55ef0ab4d5a863d934be1849c216bd [file] [log] [blame]
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
part of '../../protobuf.dart';
void _writeToCodedBufferWriter(_FieldSet fs, CodedBufferWriter out) {
// Sorting by tag number isn't required, but it sometimes enables
// performance optimizations for the receiver. See:
// https://developers.google.com/protocol-buffers/docs/encoding?hl=en#order
for (final fi in fs._infosSortedByTag) {
final value = fs._values[fi.index!];
if (value == null) continue;
out.writeField(fi.tagNumber, fi.type, value);
}
final extensions = fs._extensions;
if (extensions != null) {
for (final tagNumber in _sorted(extensions._tagNumbers)) {
final fi = extensions._getInfoOrNull(tagNumber)!;
out.writeField(tagNumber, fi.type, extensions._getFieldOrNull(fi));
}
}
final unknownFields = fs._unknownFields;
if (unknownFields != null) {
unknownFields.writeToCodedBufferWriter(out);
}
}
void _mergeFromCodedBufferReader(BuilderInfo meta, _FieldSet fs,
CodedBufferReader input, ExtensionRegistry registry) {
fs._ensureWritable();
while (true) {
final tag = input.readTag();
if (tag == 0) return;
final wireType = tag & 0x7;
final tagNumber = tag >> 3;
var fi = fs._nonExtensionInfo(meta, tagNumber);
fi ??= registry.getExtension(meta.qualifiedMessageName, tagNumber);
if (fi == null || !_wireTypeMatches(fi.type, wireType)) {
if (!fs._ensureUnknownFields().mergeFieldFromBuffer(tag, input)) {
return;
}
continue;
}
// Ignore required/optional packed/unpacked.
var fieldType = fi.type;
fieldType &= ~(PbFieldType._PACKED_BIT | PbFieldType._REQUIRED_BIT);
switch (fieldType) {
case PbFieldType._OPTIONAL_BOOL:
fs._setFieldUnchecked(meta, fi, input.readBool());
break;
case PbFieldType._OPTIONAL_BYTES:
fs._setFieldUnchecked(meta, fi, input.readBytes());
break;
case PbFieldType._OPTIONAL_STRING:
fs._setFieldUnchecked(meta, fi, input.readString());
break;
case PbFieldType._OPTIONAL_FLOAT:
fs._setFieldUnchecked(meta, fi, input.readFloat());
break;
case PbFieldType._OPTIONAL_DOUBLE:
fs._setFieldUnchecked(meta, fi, input.readDouble());
break;
case PbFieldType._OPTIONAL_ENUM:
final rawValue = input.readEnum();
final value = meta._decodeEnum(tagNumber, registry, rawValue);
if (value == null) {
final unknown = fs._ensureUnknownFields();
unknown.mergeVarintField(tagNumber, Int64(rawValue));
} else {
fs._setFieldUnchecked(meta, fi, value);
}
break;
case PbFieldType._OPTIONAL_GROUP:
final subMessage = meta._makeEmptyMessage(tagNumber, registry);
final oldValue = fs._getFieldOrNull(fi);
if (oldValue != null) {
subMessage.mergeFromMessage(oldValue);
}
input.readGroup(tagNumber, subMessage, registry);
fs._setFieldUnchecked(meta, fi, subMessage);
break;
case PbFieldType._OPTIONAL_INT32:
fs._setFieldUnchecked(meta, fi, input.readInt32());
break;
case PbFieldType._OPTIONAL_INT64:
fs._setFieldUnchecked(meta, fi, input.readInt64());
break;
case PbFieldType._OPTIONAL_SINT32:
fs._setFieldUnchecked(meta, fi, input.readSint32());
break;
case PbFieldType._OPTIONAL_SINT64:
fs._setFieldUnchecked(meta, fi, input.readSint64());
break;
case PbFieldType._OPTIONAL_UINT32:
fs._setFieldUnchecked(meta, fi, input.readUint32());
break;
case PbFieldType._OPTIONAL_UINT64:
fs._setFieldUnchecked(meta, fi, input.readUint64());
break;
case PbFieldType._OPTIONAL_FIXED32:
fs._setFieldUnchecked(meta, fi, input.readFixed32());
break;
case PbFieldType._OPTIONAL_FIXED64:
fs._setFieldUnchecked(meta, fi, input.readFixed64());
break;
case PbFieldType._OPTIONAL_SFIXED32:
fs._setFieldUnchecked(meta, fi, input.readSfixed32());
break;
case PbFieldType._OPTIONAL_SFIXED64:
fs._setFieldUnchecked(meta, fi, input.readSfixed64());
break;
case PbFieldType._OPTIONAL_MESSAGE:
final GeneratedMessage? oldValue = fs._getFieldOrNull(fi);
if (oldValue != null) {
input.readMessage(oldValue, registry);
} else {
final subMessage = meta._makeEmptyMessage(tagNumber, registry);
input.readMessage(subMessage, registry);
fs._setFieldUnchecked(meta, fi, subMessage);
}
break;
case PbFieldType._REPEATED_BOOL:
final list = fs._ensureRepeatedField(meta, fi);
if (wireType == WIRETYPE_LENGTH_DELIMITED) {
final limit = input.readInt32();
if (limit != 0) {
list._checkModifiable('add');
// No need to check the element as for `bool` fields we only need to
// check that the value is not null, and we know in `add` below that
// the value isn't null (`readBool` doesn't return `null`).
input._withLimit(limit, () {
while (!input.isAtEnd()) {
list._addUnchecked(input.readBool());
}
});
}
} else {
list._checkModifiable('add');
list._addUnchecked(input.readBool());
}
break;
case PbFieldType._REPEATED_BYTES:
final list = fs._ensureRepeatedField(meta, fi);
list._checkModifiable('add');
list._addUnchecked(input.readBytes());
break;
case PbFieldType._REPEATED_STRING:
final list = fs._ensureRepeatedField(meta, fi);
list._checkModifiable('add');
list._addUnchecked(input.readString());
break;
case PbFieldType._REPEATED_FLOAT:
final list = fs._ensureRepeatedField(meta, fi);
if (wireType == WIRETYPE_LENGTH_DELIMITED) {
final limit = input.readInt32();
if (limit != 0) {
list._checkModifiable('add');
input._withLimit(limit, () {
while (!input.isAtEnd()) {
list._addUnchecked(input.readFloat());
}
});
}
} else {
list._checkModifiable('add');
list._addUnchecked(input.readFloat());
}
break;
case PbFieldType._REPEATED_DOUBLE:
final list = fs._ensureRepeatedField(meta, fi);
if (wireType == WIRETYPE_LENGTH_DELIMITED) {
final limit = input.readInt32();
if (limit != 0) {
list._checkModifiable('add');
input._withLimit(limit, () {
while (!input.isAtEnd()) {
list._addUnchecked(input.readDouble());
}
});
}
} else {
list._checkModifiable('add');
list._addUnchecked(input.readDouble());
}
break;
case PbFieldType._REPEATED_ENUM:
final list = fs._ensureRepeatedField(meta, fi);
_readPackableToListEnum(
list, meta, fs, input, wireType, tagNumber, registry);
break;
case PbFieldType._REPEATED_GROUP:
final subMessage = meta._makeEmptyMessage(tagNumber, registry);
input.readGroup(tagNumber, subMessage, registry);
final list = fs._ensureRepeatedField(meta, fi);
list.add(subMessage);
break;
case PbFieldType._REPEATED_INT32:
final list = fs._ensureRepeatedField(meta, fi);
if (wireType == WIRETYPE_LENGTH_DELIMITED) {
final limit = input.readInt32();
if (limit != 0) {
list._checkModifiable('add');
input._withLimit(limit, () {
while (!input.isAtEnd()) {
list._addUnchecked(input.readInt32());
}
});
}
} else {
list._checkModifiable('add');
list._addUnchecked(input.readInt32());
}
break;
case PbFieldType._REPEATED_INT64:
final list = fs._ensureRepeatedField(meta, fi);
if (wireType == WIRETYPE_LENGTH_DELIMITED) {
final limit = input.readInt32();
if (limit != 0) {
list._checkModifiable('add');
input._withLimit(limit, () {
while (!input.isAtEnd()) {
list._addUnchecked(input.readInt64());
}
});
}
} else {
list._checkModifiable('add');
list._addUnchecked(input.readInt64());
}
break;
case PbFieldType._REPEATED_SINT32:
final list = fs._ensureRepeatedField(meta, fi);
if (wireType == WIRETYPE_LENGTH_DELIMITED) {
final limit = input.readInt32();
if (limit != 0) {
list._checkModifiable('add');
input._withLimit(limit, () {
while (!input.isAtEnd()) {
list._addUnchecked(input.readSint32());
}
});
}
} else {
list._checkModifiable('add');
list._addUnchecked(input.readSint32());
}
break;
case PbFieldType._REPEATED_SINT64:
final list = fs._ensureRepeatedField(meta, fi);
if (wireType == WIRETYPE_LENGTH_DELIMITED) {
final limit = input.readInt32();
if (limit != 0) {
list._checkModifiable('add');
input._withLimit(limit, () {
while (!input.isAtEnd()) {
list._addUnchecked(input.readSint64());
}
});
}
} else {
list._checkModifiable('add');
list._addUnchecked(input.readSint64());
}
break;
case PbFieldType._REPEATED_UINT32:
final list = fs._ensureRepeatedField(meta, fi);
if (wireType == WIRETYPE_LENGTH_DELIMITED) {
final limit = input.readInt32();
if (limit != 0) {
list._checkModifiable('add');
input._withLimit(limit, () {
while (!input.isAtEnd()) {
list._addUnchecked(input.readUint32());
}
});
}
} else {
list._checkModifiable('add');
list._addUnchecked(input.readUint32());
}
break;
case PbFieldType._REPEATED_UINT64:
final list = fs._ensureRepeatedField(meta, fi);
if (wireType == WIRETYPE_LENGTH_DELIMITED) {
final limit = input.readInt32();
if (limit != 0) {
list._checkModifiable('add');
input._withLimit(limit, () {
while (!input.isAtEnd()) {
list._addUnchecked(input.readUint64());
}
});
}
} else {
list._checkModifiable('add');
list._addUnchecked(input.readUint64());
}
break;
case PbFieldType._REPEATED_FIXED32:
final list = fs._ensureRepeatedField(meta, fi);
if (wireType == WIRETYPE_LENGTH_DELIMITED) {
final limit = input.readInt32();
if (limit != 0) {
list._checkModifiable('add');
input._withLimit(limit, () {
while (!input.isAtEnd()) {
list._addUnchecked(input.readFixed32());
}
});
}
} else {
list._checkModifiable('add');
list._addUnchecked(input.readFixed32());
}
break;
case PbFieldType._REPEATED_FIXED64:
final list = fs._ensureRepeatedField(meta, fi);
if (wireType == WIRETYPE_LENGTH_DELIMITED) {
final limit = input.readInt32();
if (limit != 0) {
list._checkModifiable('add');
input._withLimit(limit, () {
while (!input.isAtEnd()) {
list._addUnchecked(input.readFixed64());
}
});
}
} else {
list._checkModifiable('add');
list._addUnchecked(input.readFixed64());
}
break;
case PbFieldType._REPEATED_SFIXED32:
final list = fs._ensureRepeatedField(meta, fi);
if (wireType == WIRETYPE_LENGTH_DELIMITED) {
final limit = input.readInt32();
if (limit != 0) {
list._checkModifiable('add');
input._withLimit(limit, () {
while (!input.isAtEnd()) {
list._addUnchecked(input.readSfixed32());
}
});
}
} else {
list._checkModifiable('add');
list._addUnchecked(input.readSfixed32());
}
break;
case PbFieldType._REPEATED_SFIXED64:
final list = fs._ensureRepeatedField(meta, fi);
if (wireType == WIRETYPE_LENGTH_DELIMITED) {
final limit = input.readInt32();
if (limit != 0) {
list._checkModifiable('add');
input._withLimit(limit, () {
while (!input.isAtEnd()) {
list._addUnchecked(input.readSfixed64());
}
});
}
} else {
list._checkModifiable('add');
list._addUnchecked(input.readSfixed64());
}
break;
case PbFieldType._REPEATED_MESSAGE:
final subMessage = meta._makeEmptyMessage(tagNumber, registry);
input.readMessage(subMessage, registry);
final list = fs._ensureRepeatedField(meta, fi);
list.add(subMessage);
break;
case PbFieldType._MAP:
final mapFieldInfo = fi as MapFieldInfo;
final mapEntryMeta = mapFieldInfo.mapEntryBuilderInfo;
fs
._ensureMapField(meta, mapFieldInfo)
._mergeEntry(mapEntryMeta, input, registry);
break;
default:
throw UnsupportedError('Unknown field type $fieldType');
}
}
}
void _readPackableToListEnum(
List list,
BuilderInfo meta,
_FieldSet fs,
CodedBufferReader input,
int wireType,
int tagNumber,
ExtensionRegistry registry) {
if (wireType == WIRETYPE_LENGTH_DELIMITED) {
// Packed.
input._withLimit(input.readInt32(), () {
while (!input.isAtEnd()) {
_readRepeatedEnum(list, meta, fs, input, tagNumber, registry);
}
});
} else {
// Not packed.
_readRepeatedEnum(list, meta, fs, input, tagNumber, registry);
}
}
void _readRepeatedEnum(List list, BuilderInfo meta, _FieldSet fs,
CodedBufferReader input, int tagNumber, ExtensionRegistry registry) {
final rawValue = input.readEnum();
final value = meta._decodeEnum(tagNumber, registry, rawValue);
if (value == null) {
final unknown = fs._ensureUnknownFields();
unknown.mergeVarintField(tagNumber, Int64(rawValue));
} else {
list.add(value);
}
}