private static void recursivelyAddDescriptors( FieldDescriptor field, Set<Descriptor> descriptors, ExtensionRegistry registry) { switch (field.getType()) { case BOOL: case BYTES: case DOUBLE: case ENUM: case FIXED32: case FIXED64: case FLOAT: case INT32: case INT64: case SFIXED32: case SFIXED64: case SINT32: case SINT64: case STRING: case UINT32: case UINT64: // Primitive types do not transitively access anything else. break; case GROUP: case MESSAGE: // Recursively adds all the fields from this nested Message. recursivelyAddDescriptors(field.getMessageType(), descriptors, registry); break; default: throw new UnsupportedOperationException( "Unexpected Protocol Buffers field type: " + field.getType()); } }
private static void writeSingleFieldNoTag( CodedOutputStream output, FieldDescriptor fd, Object value) throws IOException { switch (fd.getType()) { case DOUBLE: output.writeDoubleNoTag((Double) value); break; case FLOAT: output.writeFloatNoTag((Float) value); break; case INT64: case UINT64: output.writeInt64NoTag((Long) value); break; case INT32: output.writeInt32NoTag((Integer) value); break; case FIXED64: output.writeFixed64NoTag((Long) value); break; case FIXED32: output.writeFixed32NoTag((Integer) value); break; case BOOL: output.writeBoolNoTag((Boolean) value); break; case STRING: output.writeStringNoTag((String) value); break; case GROUP: case MESSAGE: output.writeMessageNoTag((Message) value); break; case BYTES: output.writeBytesNoTag((ByteString) value); break; case UINT32: output.writeUInt32NoTag((Integer) value); break; case ENUM: output.writeEnumNoTag(((ProtocolMessageEnum) value).getNumber()); break; case SFIXED32: output.writeSFixed32NoTag((Integer) value); break; case SFIXED64: output.writeSFixed64NoTag((Long) value); break; case SINT32: output.writeSInt32NoTag((Integer) value); break; case SINT64: output.writeSInt64NoTag((Integer) value); break; default: throw new IllegalArgumentException( "Unknown type " + fd.getType() + " for " + fd.getFullName()); } }
private void printSingleField(final FieldDescriptor field, final Object value, final TextGenerator generator) throws IOException { if (field.isExtension()) { generator.print("["); // We special-case MessageSet elements for compatibility with proto1. if (field.getContainingType().getOptions().getMessageSetWireFormat() && (field.getType() == FieldDescriptor.Type.MESSAGE) && (field.isOptional()) // object equality && (field.getExtensionScope() == field.getMessageType())) { generator.print(field.getMessageType().getFullName()); } else { generator.print(field.getFullName()); } generator.print("]"); } else { if (field.getType() == FieldDescriptor.Type.GROUP) { // Groups must be serialized with their original capitalization. generator.print(field.getMessageType().getName()); } else { generator.print(field.getName()); } } if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { if (singleLineMode) { generator.print(" { "); } else { generator.print(" {\n"); generator.indent(); } } else { generator.print(": "); } printFieldValue(field, value, generator); if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { if (singleLineMode) { generator.print("} "); } else { generator.outdent(); generator.print("}\n"); } } else { if (singleLineMode) { generator.print(" "); } else { generator.print("\n"); } } }
private static Object readSingleFieldNoTag( CodedInputStream input, FieldDescriptor fd, Builder enclosingBuilder) throws IOException { switch (fd.getType()) { case DOUBLE: return input.readDouble(); case FLOAT: return input.readFloat(); case INT64: case UINT64: return input.readInt64(); case INT32: return input.readInt32(); case FIXED64: return input.readFixed64(); case FIXED32: return input.readFixed32(); case BOOL: return input.readBool(); case STRING: return input.readString(); case GROUP: case MESSAGE: Builder fieldBuilder = enclosingBuilder.newBuilderForField(fd); input.readMessage(fieldBuilder, null); return fieldBuilder.build(); case BYTES: return input.readBytes(); case UINT32: return input.readUInt32(); case ENUM: EnumValueDescriptor eVal = fd.getEnumType().findValueByNumber(input.readEnum()); // ideally if a given enum does not exist, we should search // unknown fields. but we don't have access to that here. return default return eVal != null ? eVal : fd.getDefaultValue(); case SFIXED32: return input.readSFixed32(); case SFIXED64: return input.readSFixed64(); case SINT32: return input.readSInt32(); case SINT64: return input.readSInt64(); default: throw new IllegalArgumentException( "Unknown type " + fd.getType() + " for " + fd.getFullName()); } }
public int getSerializedSize() { int size = memoizedSize; if (size != -1) { return size; } size = 0; final boolean isMessageSet = getDescriptorForType().getOptions().getMessageSetWireFormat(); for (final Map.Entry<FieldDescriptor, Object> entry : getAllFields().entrySet()) { final FieldDescriptor field = entry.getKey(); final Object value = entry.getValue(); if (isMessageSet && field.isExtension() && field.getType() == FieldDescriptor.Type.MESSAGE && !field.isRepeated()) { size += CodedOutputStream.computeMessageSetExtensionSize(field.getNumber(), (Message) value); } else { size += FieldSet.computeFieldSize(field, value); } } final UnknownFieldSet unknownFields = getUnknownFields(); if (isMessageSet) { size += unknownFields.getSerializedSizeAsMessageSet(); } else { size += unknownFields.getSerializedSize(); } memoizedSize = size; return size; }
protected static void filterValue( boolean clearEmpty, Predicate<FieldDescriptor> filter, Message.Builder builder, Map.Entry<FieldDescriptor, Object> entry) { FieldDescriptor fd = entry.getKey(); Object value = entry.getValue(); if (fd.getType() == FieldDescriptor.Type.MESSAGE) { if (fd.isRepeated()) { for (Object obj : ((Iterable<?>) value)) { Message child = filter((Message) obj, clearEmpty, filter); if (child != null) { builder.addRepeatedField(fd, child); } } } else { Message child = filter((Message) value, clearEmpty, filter); if (child != null) { builder.setField(fd, child); } } } else { builder.setField(fd, value); } }
/** * Converts a tupleField string to its corresponding protobuf enum type if necessary, otherwise * returns the tupleField as is. * * @param fieldDescriptor the FieldDescriptor for the given tuple field * @param tupleField the tupleField being converted to a protobuf field * @return the protobuf type for the given tupleField. This will be the tupleField itself unless * it's an enum, in which case this will return the enum type for the field. */ public Object tupleFieldToSingleField(FieldDescriptor fieldDescriptor, Object tupleField) { if (fieldDescriptor.getType() == FieldDescriptor.Type.ENUM) { // Convert tupleField to the enum value. return fieldDescriptor.getEnumType().findValueByName((String) tupleField); } else { return tupleField; } }
private static void getRepeatedFieldNamesInternal(Descriptor d, Map<String, Set<String>> result) { Set<String> repeatedFields = Sets.newHashSet(); for (FieldDescriptor fd : d.getFields()) { if (fd.isRepeated()) { repeatedFields.add(javaCase(fd.getName())); } if (fd.getType() == FieldDescriptor.Type.MESSAGE) { getRepeatedFieldNamesInternal(fd.getMessageType(), result); } } if (!repeatedFields.isEmpty()) { result.put(javaCase(d.getName()), repeatedFields); } }
/** Get a hash code for given fields and values, using the given seed. */ @SuppressWarnings("unchecked") protected int hashFields(int hash, Map<FieldDescriptor, Object> map) { for (Map.Entry<FieldDescriptor, Object> entry : map.entrySet()) { FieldDescriptor field = entry.getKey(); Object value = entry.getValue(); hash = (37 * hash) + field.getNumber(); if (field.getType() != FieldDescriptor.Type.ENUM) { hash = (53 * hash) + value.hashCode(); } else if (field.isRepeated()) { List<? extends EnumLite> list = (List<? extends EnumLite>) value; hash = (53 * hash) + hashEnumList(list); } else { hash = (53 * hash) + hashEnum((EnumLite) value); } } return hash; }
public Builder setField(FieldDescriptor field, Object value) { verifyContainingType(field); ensureIsMutable(); if (field.getType() == FieldDescriptor.Type.ENUM) { verifyEnumType(field, value); } OneofDescriptor oneofDescriptor = field.getContainingOneof(); if (oneofDescriptor != null) { int index = oneofDescriptor.getIndex(); FieldDescriptor oldField = oneofCases[index]; if ((oldField != null) && (oldField != field)) { fields.clearField(oldField); } oneofCases[index] = field; } fields.setField(field, value); return this; }
/** * Turn a Tuple into a Message with the given type. * * @param builder a builder for the Message type the tuple will be converted to * @param tuple the tuple * @return a message representing the given tuple */ public Message tupleToMessage(Builder builder, Tuple tuple) { List<FieldDescriptor> fieldDescriptors = builder.getDescriptorForType().getFields(); if (tuple == null) { return builder.build(); } for (int i = 0; i < fieldDescriptors.size() && i < tuple.size(); i++) { Object tupleField = null; FieldDescriptor fieldDescriptor = fieldDescriptors.get(i); try { tupleField = tuple.get(i); } catch (ExecException e) { LOG.warn( "Could not convert tuple field " + tupleField + " to field with descriptor " + fieldDescriptor); continue; } if (tupleField != null) { if (fieldDescriptor.isRepeated()) { // Repeated fields are set with Lists containing objects of the fields' Java type. builder.setField( fieldDescriptor, dataBagToRepeatedField(builder, fieldDescriptor, (DataBag) tupleField)); } else { if (fieldDescriptor.getType() == FieldDescriptor.Type.MESSAGE) { Builder nestedMessageBuilder = builder.newBuilderForField(fieldDescriptor); builder.setField( fieldDescriptor, tupleToMessage((Builder) nestedMessageBuilder, (Tuple) tupleField)); } else { builder.setField(fieldDescriptor, tupleFieldToSingleField(fieldDescriptor, tupleField)); } } } } return builder.build(); }
/** * Converts a DataBag into a List of objects with the type in the given FieldDescriptor. DataBags * don't map cleanly to repeated protobuf types, so each Tuple has to be unwrapped (by taking the * first element if the type is primitive or by converting the Tuple to a Message if the type is * MESSAGE), and the contents have to be appended to a List. * * @param containingMessageBuilder a Message builder for the Message that contains this repeated * field * @param fieldDescriptor a FieldDescriptor for this repeated field * @param bag the DataBag being serialized * @return a protobuf-friendly List of fieldDescriptor-type objects */ public List<Object> dataBagToRepeatedField( Builder containingMessageBuilder, FieldDescriptor fieldDescriptor, DataBag bag) { ArrayList<Object> bagContents = new ArrayList<Object>((int) bag.size()); Iterator<Tuple> bagIter = bag.iterator(); while (bagIter.hasNext()) { Tuple tuple = bagIter.next(); if (fieldDescriptor.getType() == FieldDescriptor.Type.MESSAGE) { Builder nestedMessageBuilder = containingMessageBuilder.newBuilderForField(fieldDescriptor); bagContents.add(tupleToMessage((Builder) nestedMessageBuilder, tuple)); } else { try { bagContents.add(tupleFieldToSingleField(fieldDescriptor, tuple.get(0))); } catch (ExecException e) { LOG.warn("Could not add a value for repeated field with descriptor " + fieldDescriptor); } } } return bagContents; }
public void writeTo(final CodedOutputStream output) throws IOException { final boolean isMessageSet = getDescriptorForType().getOptions().getMessageSetWireFormat(); for (final Map.Entry<FieldDescriptor, Object> entry : getAllFields().entrySet()) { final FieldDescriptor field = entry.getKey(); final Object value = entry.getValue(); if (isMessageSet && field.isExtension() && field.getType() == FieldDescriptor.Type.MESSAGE && !field.isRepeated()) { output.writeMessageSetExtension(field.getNumber(), (Message) value); } else { FieldSet.writeField(field, value, output); } } final UnknownFieldSet unknownFields = getUnknownFields(); if (isMessageSet) { unknownFields.writeAsMessageSetTo(output); } else { unknownFields.writeTo(output); } }
/** * Like {@link #mergeFrom(CodedInputStream, ExtensionRegistryLite)}, but parses a single field. * * <p>When {@code builder} is not null, the method will parse and merge the field into {@code * builder}. Otherwise, it will try to parse the field into {@code extensions}, when it's called * by the parsing constructor in generated classes. * * <p>Package-private because it is used by GeneratedMessage.ExtendableMessage. * * @param tag The tag, which should have already been read. * @return {@code true} unless the tag is an end-group tag. */ static boolean mergeFieldFrom( CodedInputStream input, UnknownFieldSet.Builder unknownFields, ExtensionRegistryLite extensionRegistry, Descriptor type, Message.Builder builder, FieldSet<FieldDescriptor> extensions, int tag) throws IOException { if (type.getOptions().getMessageSetWireFormat() && tag == WireFormat.MESSAGE_SET_ITEM_TAG) { mergeMessageSetExtensionFromCodedStream( input, unknownFields, extensionRegistry, type, builder, extensions); return true; } final int wireType = WireFormat.getTagWireType(tag); final int fieldNumber = WireFormat.getTagFieldNumber(tag); final FieldDescriptor field; Message defaultInstance = null; if (type.isExtensionNumber(fieldNumber)) { // extensionRegistry may be either ExtensionRegistry or // ExtensionRegistryLite. Since the type we are parsing is a full // message, only a full ExtensionRegistry could possibly contain // extensions of it. Otherwise we will treat the registry as if it // were empty. if (extensionRegistry instanceof ExtensionRegistry) { final ExtensionRegistry.ExtensionInfo extension = ((ExtensionRegistry) extensionRegistry).findExtensionByNumber(type, fieldNumber); if (extension == null) { field = null; } else { field = extension.descriptor; defaultInstance = extension.defaultInstance; if (defaultInstance == null && field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { throw new IllegalStateException( "Message-typed extension lacked default instance: " + field.getFullName()); } } } else { field = null; } } else if (builder != null) { field = type.findFieldByNumber(fieldNumber); } else { field = null; } boolean unknown = false; boolean packed = false; if (field == null) { unknown = true; // Unknown field. } else if (wireType == FieldSet.getWireFormatForFieldType(field.getLiteType(), false /* isPacked */)) { packed = false; } else if (field.isPackable() && wireType == FieldSet.getWireFormatForFieldType(field.getLiteType(), true /* isPacked */)) { packed = true; } else { unknown = true; // Unknown wire type. } if (unknown) { // Unknown field or wrong wire type. Skip. return unknownFields.mergeFieldFrom(tag, input); } if (packed) { final int length = input.readRawVarint32(); final int limit = input.pushLimit(length); if (field.getLiteType() == WireFormat.FieldType.ENUM) { while (input.getBytesUntilLimit() > 0) { final int rawValue = input.readEnum(); final Object value = field.getEnumType().findValueByNumber(rawValue); if (value == null) { // If the number isn't recognized as a valid value for this // enum, drop it (don't even add it to unknownFields). return true; } addRepeatedField(builder, extensions, field, value); } } else { while (input.getBytesUntilLimit() > 0) { final Object value = FieldSet.readPrimitiveField(input, field.getLiteType()); addRepeatedField(builder, extensions, field, value); } } input.popLimit(limit); } else { final Object value; switch (field.getType()) { case GROUP: { final Message.Builder subBuilder; if (defaultInstance != null) { subBuilder = defaultInstance.newBuilderForType(); } else { subBuilder = builder.newBuilderForField(field); } if (!field.isRepeated()) { mergeOriginalMessage(builder, extensions, field, subBuilder); } input.readGroup(field.getNumber(), subBuilder, extensionRegistry); value = subBuilder.buildPartial(); break; } case MESSAGE: { final Message.Builder subBuilder; if (defaultInstance != null) { subBuilder = defaultInstance.newBuilderForType(); } else { subBuilder = builder.newBuilderForField(field); } if (!field.isRepeated()) { mergeOriginalMessage(builder, extensions, field, subBuilder); } input.readMessage(subBuilder, extensionRegistry); value = subBuilder.buildPartial(); break; } case ENUM: final int rawValue = input.readEnum(); value = field.getEnumType().findValueByNumber(rawValue); // If the number isn't recognized as a valid value for this enum, // drop it. if (value == null) { unknownFields.mergeVarintField(fieldNumber, rawValue); return true; } break; default: value = FieldSet.readPrimitiveField(input, field.getLiteType()); break; } if (field.isRepeated()) { addRepeatedField(builder, extensions, field, value); } else { setField(builder, extensions, field, value); } } return true; }
/** * Like {@link #mergeFrom(CodedInputStream, UnknownFieldSet.Builder, ExtensionRegistryLite, * Message.Builder)}, but parses a single field. Package-private because it is used by * GeneratedMessage.ExtendableMessage. * * @param tag The tag, which should have already been read. * @return {@code true} unless the tag is an end-group tag. */ @SuppressWarnings("unchecked") static boolean mergeFieldFrom( final CodedInputStream input, final UnknownFieldSet.Builder unknownFields, final ExtensionRegistryLite extensionRegistry, final Message.Builder builder, final int tag) throws IOException { final Descriptor type = builder.getDescriptorForType(); if (type.getOptions().getMessageSetWireFormat() && tag == WireFormat.MESSAGE_SET_ITEM_TAG) { mergeMessageSetExtensionFromCodedStream(input, unknownFields, extensionRegistry, builder); return true; } final int wireType = WireFormat.getTagWireType(tag); final int fieldNumber = WireFormat.getTagFieldNumber(tag); final FieldDescriptor field; Message defaultInstance = null; if (type.isExtensionNumber(fieldNumber)) { // extensionRegistry may be either ExtensionRegistry or // ExtensionRegistryLite. Since the type we are parsing is a full // message, only a full ExtensionRegistry could possibly contain // extensions of it. Otherwise we will treat the registry as if it // were empty. if (extensionRegistry instanceof ExtensionRegistry) { final ExtensionRegistry.ExtensionInfo extension = ((ExtensionRegistry) extensionRegistry).findExtensionByNumber(type, fieldNumber); if (extension == null) { field = null; } else { field = extension.descriptor; defaultInstance = extension.defaultInstance; } } else { field = null; } } else { field = type.findFieldByNumber(fieldNumber); } if (field == null || wireType != FieldSet.getWireFormatForFieldType( field.getLiteType(), field.getOptions().getPacked())) { // Unknown field or wrong wire type. Skip. return unknownFields.mergeFieldFrom(tag, input); } if (field.getOptions().getPacked()) { final int length = input.readRawVarint32(); final int limit = input.pushLimit(length); if (field.getLiteType() == WireFormat.FieldType.ENUM) { while (input.getBytesUntilLimit() > 0) { final int rawValue = input.readEnum(); final Object value = field.getEnumType().findValueByNumber(rawValue); if (value == null) { // If the number isn't recognized as a valid value for this // enum, drop it (don't even add it to unknownFields). return true; } builder.addRepeatedField(field, value); } } else { while (input.getBytesUntilLimit() > 0) { final Object value = FieldSet.readPrimitiveField(input, field.getLiteType()); builder.addRepeatedField(field, value); } } input.popLimit(limit); } else { final Object value; switch (field.getType()) { case GROUP: { final Message.Builder subBuilder; if (defaultInstance != null) { subBuilder = defaultInstance.newBuilderForType(); } else { subBuilder = builder.newBuilderForField(field); } if (!field.isRepeated()) { subBuilder.mergeFrom((Message) builder.getField(field)); } input.readGroup(field.getNumber(), subBuilder, extensionRegistry); value = subBuilder.build(); break; } case MESSAGE: { final Message.Builder subBuilder; if (defaultInstance != null) { subBuilder = defaultInstance.newBuilderForType(); } else { subBuilder = builder.newBuilderForField(field); } if (!field.isRepeated()) { subBuilder.mergeFrom((Message) builder.getField(field)); } input.readMessage(subBuilder, extensionRegistry); value = subBuilder.build(); break; } case ENUM: final int rawValue = input.readEnum(); value = field.getEnumType().findValueByNumber(rawValue); // If the number isn't recognized as a valid value for this enum, // drop it. if (value == null) { unknownFields.mergeVarintField(fieldNumber, rawValue); return true; } break; default: value = FieldSet.readPrimitiveField(input, field.getLiteType()); break; } if (field.isRepeated()) { builder.addRepeatedField(field, value); } else { builder.setField(field, value); } } return true; }
private void printFieldValue(final FieldDescriptor field, final Object value, final TextGenerator generator) throws IOException { switch (field.getType()) { case INT32: case SINT32: case SFIXED32: generator.print(((Integer) value).toString()); break; case INT64: case SINT64: case SFIXED64: generator.print(((Long) value).toString()); break; case BOOL: generator.print(((Boolean) value).toString()); break; case FLOAT: generator.print(((Float) value).toString()); break; case DOUBLE: generator.print(((Double) value).toString()); break; case UINT32: case FIXED32: generator.print(unsignedToString((Integer) value)); break; case UINT64: case FIXED64: generator.print(unsignedToString((Long) value)); break; case STRING: generator.print("\""); generator.print(escapeNonAscii ? escapeText((String) value) : escapeDoubleQuotesAndBackslashes((String) value) .replace("\n", "\\n")); generator.print("\""); break; case BYTES: generator.print("\""); if (value instanceof ByteString) { generator.print(escapeBytes((ByteString) value)); } else { generator.print(escapeBytes((byte[]) value)); } generator.print("\""); break; case ENUM: generator.print(((EnumValueDescriptor) value).getName()); break; case MESSAGE: case GROUP: print((Message) value, generator); break; } }