blob: 486c62ecce0a9fd3e9d4e279700e97211354f509 [file] [log] [blame]
// Copyright (c) 2011, 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_serializers;
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 (var fi in fs.infosSortedByTag) {
var value = fs.values[fi.index!];
if (value == null) continue;
out.writeField(fi.tagNumber, fi.type, value);
}
if (fs.hasExtensions) {
for (var tagNumber in _sorted(fs.extensions!.tagNumbers)) {
var fi = fs.extensions!.getInfoOrNull(tagNumber)!;
out.writeField(tagNumber, fi.type, fs.extensions!.getFieldOrNull(fi));
}
}
if (fs.hasUnknownFields) {
final fields = fs.unknownFields!.fields;
for (var key in fields.keys) {
final UnknownFieldSetField value = fields[key]!;
out.writeField(key, PbFieldType.REPEATED_UINT64, value.varints);
out.writeField(key, PbFieldType.REPEATED_FIXED32, value.fixed32s);
out.writeField(key, PbFieldType.REPEATED_FIXED64, value.fixed64s);
out.writeField(key, PbFieldType.REPEATED_BYTES, value.lengthDelimited);
out.writeField(key, PbFieldType.REPEATED_GROUP, value.groups);
}
}
}
void mergeFromCodedBufferReader(BuilderInfo meta, FieldSet fs,
CodedBufferReader input, ExtensionRegistry registry) {
ArgumentError.checkNotNull(registry);
while (true) {
var tag = input.readTag();
if (tag == 0) return;
var wireType = tag & 0x7;
var tagNumber = tag >> 3;
var fi = fs.nonExtensionInfo(meta, tagNumber);
fi ??= registry.getExtension(meta.qualifiedMessageName, tagNumber);
if (fi == null || !_wireTypeMatches(fi.type, wireType)) {
if (!input._mergeField(tag, fs.ensureUnknownFields())) {
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:
var rawValue = input.readEnum();
var value = meta.decodeEnum(tagNumber, registry, rawValue);
if (value == null) {
var unknown = fs.ensureUnknownFields();
unknown.mergeVarintField(tagNumber, Int64(rawValue));
} else {
fs.setFieldUnchecked(meta, fi, value);
}
break;
case PbFieldType.OPTIONAL_GROUP:
var subMessage = meta.makeEmptyMessage(tagNumber, registry);
var 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:
var subMessage = meta.makeEmptyMessage(tagNumber, registry);
var oldValue = fs.getFieldOrNull(fi);
if (oldValue != null) {
subMessage.mergeFromMessage(oldValue);
}
input.readMessage(subMessage, registry);
fs.setFieldUnchecked(meta, fi, subMessage);
break;
case PbFieldType.REPEATED_BOOL:
_readPackable(meta, fs, input, wireType, fi, input.readBool);
break;
case PbFieldType.REPEATED_BYTES:
fs.ensureRepeatedField(meta, fi).add(input.readBytes());
break;
case PbFieldType.REPEATED_STRING:
fs.ensureRepeatedField(meta, fi).add(input.readString());
break;
case PbFieldType.REPEATED_FLOAT:
_readPackable(meta, fs, input, wireType, fi, input.readFloat);
break;
case PbFieldType.REPEATED_DOUBLE:
_readPackable(meta, fs, input, wireType, fi, input.readDouble);
break;
case PbFieldType.REPEATED_ENUM:
_readPackableToListEnum(
meta, fs, input, wireType, fi, tagNumber, registry);
break;
case PbFieldType.REPEATED_GROUP:
var subMessage = meta.makeEmptyMessage(tagNumber, registry);
input.readGroup(tagNumber, subMessage, registry);
fs.ensureRepeatedField(meta, fi).add(subMessage);
break;
case PbFieldType.REPEATED_INT32:
_readPackable(meta, fs, input, wireType, fi, input.readInt32);
break;
case PbFieldType.REPEATED_INT64:
_readPackable(meta, fs, input, wireType, fi, input.readInt64);
break;
case PbFieldType.REPEATED_SINT32:
_readPackable(meta, fs, input, wireType, fi, input.readSint32);
break;
case PbFieldType.REPEATED_SINT64:
_readPackable(meta, fs, input, wireType, fi, input.readSint64);
break;
case PbFieldType.REPEATED_UINT32:
_readPackable(meta, fs, input, wireType, fi, input.readUint32);
break;
case PbFieldType.REPEATED_UINT64:
_readPackable(meta, fs, input, wireType, fi, input.readUint64);
break;
case PbFieldType.REPEATED_FIXED32:
_readPackable(meta, fs, input, wireType, fi, input.readFixed32);
break;
case PbFieldType.REPEATED_FIXED64:
_readPackable(meta, fs, input, wireType, fi, input.readFixed64);
break;
case PbFieldType.REPEATED_SFIXED32:
_readPackable(meta, fs, input, wireType, fi, input.readSfixed32);
break;
case PbFieldType.REPEATED_SFIXED64:
_readPackable(meta, fs, input, wireType, fi, input.readSfixed64);
break;
case PbFieldType.REPEATED_MESSAGE:
var subMessage = meta.makeEmptyMessage(tagNumber, registry);
input.readMessage(subMessage, registry);
fs.ensureRepeatedField(meta, fi).add(subMessage);
break;
case PbFieldType.MAP:
final mapFieldInfo = fi as MapFieldInfo;
final mapEntryMeta = mapFieldInfo.mapEntryBuilderInfo;
input._mergeMapEntry(
mapEntryMeta, fs.ensureMapField(meta, mapFieldInfo), registry);
break;
default:
throw 'Unknown field type $fieldType';
}
}
}
void _readPackable(BuilderInfo meta, FieldSet fs, CodedBufferReader input,
int wireType, FieldInfo fi, Function readFunc) {
void readToList(List list) => list.add(readFunc());
_readPackableToList(meta, fs, input, wireType, fi, readToList);
}
void _readPackableToListEnum(
BuilderInfo meta,
FieldSet fs,
CodedBufferReader input,
int wireType,
FieldInfo fi,
int tagNumber,
ExtensionRegistry registry) {
void readToList(List list) {
var rawValue = input.readEnum();
var value = meta.decodeEnum(tagNumber, registry, rawValue);
if (value == null) {
var unknown = fs.ensureUnknownFields();
unknown.mergeVarintField(tagNumber, Int64(rawValue));
} else {
list.add(value);
}
}
_readPackableToList(meta, fs, input, wireType, fi, readToList);
}
void _readPackableToList(BuilderInfo meta, FieldSet fs, CodedBufferReader input,
int wireType, FieldInfo fi, Function readToList) {
var list = fs.ensureRepeatedField(meta, fi);
if (wireType == WIRETYPE_LENGTH_DELIMITED) {
// Packed.
input._withLimit(input.readInt32(), () {
while (!input.isAtEnd()) {
readToList(list);
}
});
} else {
// Not packed.
readToList(list);
}
}
List<T> _sorted<T>(Iterable<T> list) => List.from(list)..sort();
int getTagFieldNumber(int tag) => tag >> TAG_TYPE_BITS;
int getTagWireType(int tag) => tag & TAG_TYPE_MASK;
/// Returns true if the wireType can be merged into the given fieldType.
bool _wireTypeMatches(int fieldType, int wireType) {
switch (PbFieldType.baseType(fieldType)) {
case PbFieldType.BOOL_BIT:
case PbFieldType.ENUM_BIT:
case PbFieldType.INT32_BIT:
case PbFieldType.INT64_BIT:
case PbFieldType.SINT32_BIT:
case PbFieldType.SINT64_BIT:
case PbFieldType.UINT32_BIT:
case PbFieldType.UINT64_BIT:
return wireType == WIRETYPE_VARINT ||
wireType == WIRETYPE_LENGTH_DELIMITED;
case PbFieldType.FLOAT_BIT:
case PbFieldType.FIXED32_BIT:
case PbFieldType.SFIXED32_BIT:
return wireType == WIRETYPE_FIXED32 ||
wireType == WIRETYPE_LENGTH_DELIMITED;
case PbFieldType.DOUBLE_BIT:
case PbFieldType.FIXED64_BIT:
case PbFieldType.SFIXED64_BIT:
return wireType == WIRETYPE_FIXED64 ||
wireType == WIRETYPE_LENGTH_DELIMITED;
case PbFieldType.BYTES_BIT:
case PbFieldType.STRING_BIT:
case PbFieldType.MESSAGE_BIT:
return wireType == WIRETYPE_LENGTH_DELIMITED;
case PbFieldType.GROUP_BIT:
return wireType == WIRETYPE_START_GROUP;
default:
return false;
}
}