blob: e9d55f91556a73e002e6ad9a20cb76d09dc58635 [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;
/// Per-message type setup.
class BuilderInfo {
final String messageName;
final Map<int, FieldInfo> fieldInfo = new Map<int, FieldInfo>();
final Map<String, FieldInfo> byTagAsString = <String, FieldInfo>{};
final Map<String, FieldInfo> byName = <String, FieldInfo>{};
bool hasExtensions = false;
bool hasRequiredFields = true;
List<FieldInfo> _sortedByTag;
BuilderInfo(this.messageName);
void add<T>(
int tagNumber,
String name,
int fieldType,
dynamic defaultOrMaker,
CreateBuilderFunc subBuilder,
ValueOfFunc valueOf,
List<ProtobufEnum> enumValues) {
var index = fieldInfo.length;
addField(new FieldInfo<T>(name, tagNumber, index, fieldType, defaultOrMaker,
subBuilder, valueOf, enumValues));
}
void addRepeated<T>(
int tagNumber,
String name,
int fieldType,
CheckFunc<T> check,
CreateBuilderFunc subBuilder,
ValueOfFunc valueOf,
List<ProtobufEnum> enumValues) {
var index = fieldInfo.length;
addField(new FieldInfo<T>.repeated(name, tagNumber, index, fieldType, check,
subBuilder, valueOf, enumValues));
}
void addField(FieldInfo fi) {
fieldInfo[fi.tagNumber] = fi;
byTagAsString["${fi.tagNumber}"] = fi;
byName[fi.name] = fi;
}
void a<T>(int tagNumber, String name, int fieldType,
[dynamic defaultOrMaker,
CreateBuilderFunc subBuilder,
ValueOfFunc valueOf,
List<ProtobufEnum> enumValues]) {
add<T>(tagNumber, name, fieldType, defaultOrMaker, subBuilder, valueOf,
enumValues);
}
// Enum.
void e<T>(int tagNumber, String name, int fieldType, dynamic defaultOrMaker,
ValueOfFunc valueOf, List<ProtobufEnum> enumValues) {
add<T>(
tagNumber, name, fieldType, defaultOrMaker, null, valueOf, enumValues);
}
// Repeated message.
// TODO(skybrian): migrate to pp() and remove.
void m<T>(int tagNumber, String name, CreateBuilderFunc subBuilder,
MakeDefaultFunc makeDefault) {
add<T>(tagNumber, name, PbFieldType._REPEATED_MESSAGE, makeDefault,
subBuilder, null, null);
}
// Repeated, not a message, group, or enum.
void p<T>(int tagNumber, String name, int fieldType) {
assert(!_isGroupOrMessage(fieldType) && !_isEnum(fieldType));
addRepeated<T>(tagNumber, name, fieldType, getCheckFunction(fieldType),
null, null, null);
}
// Repeated message, group, or enum.
void pp<T>(int tagNumber, String name, int fieldType, CheckFunc<T> check,
[CreateBuilderFunc subBuilder,
ValueOfFunc valueOf,
List<ProtobufEnum> enumValues]) {
assert(_isGroupOrMessage(fieldType) || _isEnum(fieldType));
addRepeated<T>(
tagNumber, name, fieldType, check, subBuilder, valueOf, enumValues);
}
bool containsTagNumber(int tagNumber) => fieldInfo.containsKey(tagNumber);
defaultValue(int tagNumber) {
MakeDefaultFunc func = makeDefault(tagNumber);
return func == null ? null : func();
}
// Returns the field name for a given tag number, for debugging purposes.
String fieldName(int tagNumber) {
FieldInfo i = fieldInfo[tagNumber];
return i != null ? i.name : null;
}
int fieldType(int tagNumber) {
FieldInfo i = fieldInfo[tagNumber];
return i != null ? i.type : null;
}
MakeDefaultFunc makeDefault(int tagNumber) {
FieldInfo i = fieldInfo[tagNumber];
return i != null ? i.makeDefault : null;
}
CreateBuilderFunc subBuilder(int tagNumber) {
FieldInfo i = fieldInfo[tagNumber];
return i != null ? i.subBuilder : null;
}
int tagNumber(String fieldName) {
FieldInfo i = byName[fieldName];
return i != null ? i.tagNumber : null;
}
ValueOfFunc valueOfFunc(int tagNumber) {
FieldInfo i = fieldInfo[tagNumber];
return i != null ? i.valueOf : null;
}
/// Returns the FieldInfo for each field in tag number order.
List<FieldInfo> get sortedByTag => _sortedByTag ??= _computeSortedByTag();
List<FieldInfo> _computeSortedByTag() {
// TODO(skybrian): perhaps the code generator should insert the FieldInfos
// in tag number order, to avoid sorting them?
return new List<FieldInfo>.from(fieldInfo.values, growable: false)
..sort((FieldInfo a, FieldInfo b) => a.tagNumber.compareTo(b.tagNumber));
}
GeneratedMessage _makeEmptyMessage(
int tagNumber, ExtensionRegistry extensionRegistry) {
CreateBuilderFunc subBuilderFunc = subBuilder(tagNumber);
if (subBuilderFunc == null && extensionRegistry != null) {
subBuilderFunc =
extensionRegistry.getExtension(messageName, tagNumber).subBuilder;
}
return subBuilderFunc();
}
_decodeEnum(int tagNumber, ExtensionRegistry registry, int rawValue) {
ValueOfFunc f = valueOfFunc(tagNumber);
if (f == null && registry != null) {
f = registry.getExtension(messageName, tagNumber).valueOf;
}
return f(rawValue);
}
}