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());
    }
  }
Example #3
0
    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;
  }
Example #6
0
  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;
   }
 }
Example #8
0
 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;
 }
Example #10
0
 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;
 }
Example #11
0
  /**
   * 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();
  }
Example #12
0
  /**
   * 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;
  }
Example #13
0
  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;
    }
Example #15
0
    /**
     * 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;
    }
Example #16
0
    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;
      }
    }