Пример #1
0
  @Override
  public <E> E readObject(String fieldName, Class<E> clazz) throws IOException {
    final FieldDescriptor fd = messageContext.marshallerDelegate.getFieldByName(fieldName);
    checkFieldRead(fd, false);

    if (fd.getType() == Type.ENUM) {
      return ctx.getMarshallerDelegate(clazz).unmarshall(fd, this, messageContext.in);
    }

    // todo validate type is compatible with readObject
    final int expectedTag = WireFormat.makeTag(fd.getNumber(), fd.getType().getWireType());
    Object o = messageContext.unknownFieldSet.consumeTag(expectedTag);
    if (o != null) {
      byte[] byteArray = (byte[]) o;
      return readNestedObject(
          fd, clazz, RawProtoStreamReaderImpl.newInstance(byteArray), byteArray.length);
    }

    while (true) {
      int tag = messageContext.in.readTag();
      if (tag == 0) {
        break;
      }
      if (tag == expectedTag) {
        return readNestedObject(fd, clazz, messageContext.in, -1);
      }
      messageContext.unknownFieldSet.readSingleField(tag, messageContext.in);
    }

    return null;
  }
Пример #2
0
 /**
  * Reads and discards a single field, given its tag value.
  *
  * @return {@code false} if the tag is an endgroup tag, in which case nothing is skipped.
  *     Otherwise, returns {@code true}.
  */
 public boolean skipField(final int tag) throws IOException {
   switch (WireFormat.getTagWireType(tag)) {
     case WireFormat.WIRETYPE_VARINT:
       skipRawVarint();
       return true;
     case WireFormat.WIRETYPE_FIXED64:
       skipRawBytes(8);
       return true;
     case WireFormat.WIRETYPE_LENGTH_DELIMITED:
       skipRawBytes(readRawVarint32());
       return true;
     case WireFormat.WIRETYPE_START_GROUP:
       skipMessage();
       checkLastTagWas(
           WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP));
       return true;
     case WireFormat.WIRETYPE_END_GROUP:
       return false;
     case WireFormat.WIRETYPE_FIXED32:
       skipRawBytes(4);
       return true;
     default:
       throw InvalidProtocolBufferException.invalidWireType();
   }
 }
  public void testBool() throws Exception {
    int num = 1;
    boolean value = true;
    int valueSize = 1;
    int tag = WireFormat.makeTag(num, FieldType.BOOL.wireType);
    int tagSize = CodedOutput.computeRawVarint32Size(tag);
    int expect = tagSize + valueSize;

    assertSize("boolean1", CodedOutput.computeBoolSize(num, value), expect);
    assertSize("boolean2", CodedOutput.getTagAndRawVarInt32Bytes(tag, 1).length, expect);
  }
Пример #4
0
 /** Read a {@code group} field value from the stream. */
 public <T extends MessageLite> T readGroup(
     final int fieldNumber, final Parser<T> parser, final ExtensionRegistryLite extensionRegistry)
     throws IOException {
   if (recursionDepth >= recursionLimit) {
     throw InvalidProtocolBufferException.recursionLimitExceeded();
   }
   ++recursionDepth;
   T result = parser.parsePartialFrom(this, extensionRegistry);
   checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
   --recursionDepth;
   return result;
 }
Пример #5
0
 /** Read a {@code group} field value from the stream. */
 public void readGroup(
     final int fieldNumber,
     final MessageLite.Builder builder,
     final ExtensionRegistryLite extensionRegistry)
     throws IOException {
   if (recursionDepth >= recursionLimit) {
     throw InvalidProtocolBufferException.recursionLimitExceeded();
   }
   ++recursionDepth;
   builder.mergeFrom(this, extensionRegistry);
   checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
   --recursionDepth;
 }
Пример #6
0
  /**
   * Tests that if we readString invalid UTF-8 bytes, no exception is thrown. Instead, the invalid
   * bytes are replaced with the Unicode "replacement character" U+FFFD.
   */
  public void testReadStringInvalidUtf8() throws Exception {
    ByteString.Output rawOutput = ByteString.newOutput();
    CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);

    int tag = WireFormat.makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED);
    output.writeRawVarint32(tag);
    output.writeRawVarint32(1);
    output.writeRawBytes(new byte[] {(byte) 0x80});
    output.flush();

    CodedInputStream input = rawOutput.toByteString().newCodedInput();
    assertEquals(tag, input.readTag());
    String text = input.readString();
    assertEquals(0xfffd, text.charAt(0));
  }
Пример #7
0
 /**
  * Reads a single field and writes it to output in wire format, given its tag value.
  *
  * @return {@code false} if the tag is an endgroup tag, in which case nothing is skipped.
  *     Otherwise, returns {@code true}.
  */
 public boolean skipField(final int tag, final CodedOutputStream output) throws IOException {
   switch (WireFormat.getTagWireType(tag)) {
     case WireFormat.WIRETYPE_VARINT:
       {
         long value = readInt64();
         output.writeRawVarint32(tag);
         output.writeUInt64NoTag(value);
         return true;
       }
     case WireFormat.WIRETYPE_FIXED64:
       {
         long value = readRawLittleEndian64();
         output.writeRawVarint32(tag);
         output.writeFixed64NoTag(value);
         return true;
       }
     case WireFormat.WIRETYPE_LENGTH_DELIMITED:
       {
         ByteString value = readBytes();
         output.writeRawVarint32(tag);
         output.writeBytesNoTag(value);
         return true;
       }
     case WireFormat.WIRETYPE_START_GROUP:
       {
         output.writeRawVarint32(tag);
         skipMessage(output);
         int endtag =
             WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP);
         checkLastTagWas(endtag);
         output.writeRawVarint32(endtag);
         return true;
       }
     case WireFormat.WIRETYPE_END_GROUP:
       {
         return false;
       }
     case WireFormat.WIRETYPE_FIXED32:
       {
         int value = readRawLittleEndian32();
         output.writeRawVarint32(tag);
         output.writeFixed32NoTag(value);
         return true;
       }
     default:
       throw InvalidProtocolBufferException.invalidWireType();
   }
 }
  public void testRawLittleEndian64Bytes() throws Exception {
    String n1 = "double1", n2 = "double2";
    for (int i = 0; i < doubleValues.length; ) {
      double[] inner = doubleValues[i++];
      int num = i;
      for (int j = 0; j < inner.length; j++) {
        long value = Double.doubleToRawLongBits(inner[j]);
        int tag = WireFormat.makeTag(num, FieldType.DOUBLE.wireType);
        int tagSize = CodedOutput.computeRawVarint32Size(tag);
        int expect = tagSize + CodedOutput.LITTLE_ENDIAN_64_SIZE;

        assertSize(n1, CodedOutput.computeDoubleSize(num, inner[j]), expect);
        assertSize(n2, CodedOutput.getTagAndRawLittleEndian64Bytes(tag, value).length, expect);
      }
    }
  }
  public void testRawVarInt32Bytes() throws Exception {
    String n1 = "int1", n2 = "int2";
    for (int i = 0; i < int32values.length; ) {
      int[] inner = int32values[i++];
      int num = i;
      for (int j = 0; j < inner.length; j++) {
        int value = inner[j];
        int valueSize = CodedOutput.computeRawVarint32Size(value);
        int tag = WireFormat.makeTag(num, FieldType.INT32.wireType);
        int tagSize = CodedOutput.computeRawVarint32Size(tag);
        int expect = tagSize + valueSize;

        assertSize(n1, CodedOutput.computeInt32Size(num, value), expect);
        assertSize(n2, CodedOutput.getTagAndRawVarInt32Bytes(tag, value).length, expect);
      }
    }
  }
  public void testRawLittleEndian32Bytes() throws Exception {
    String n1 = "float1", n2 = "float2";
    for (int i = 0; i < floatValues.length; ) {
      float[] inner = floatValues[i++];
      int num = i;
      for (int j = 0; j < inner.length; j++) {
        int value = Float.floatToRawIntBits(inner[j]);
        int valueSize = CodedOutput.LITTLE_ENDIAN_32_SIZE;
        int tag = WireFormat.makeTag(num, FieldType.FLOAT.wireType);
        int tagSize = CodedOutput.computeRawVarint32Size(tag);
        int expect = tagSize + valueSize;

        assertSize(n1, CodedOutput.computeFloatSize(num, inner[j]), expect);
        assertSize(n2, CodedOutput.getTagAndRawLittleEndian32Bytes(tag, value).length, expect);
      }
    }
  }
Пример #11
0
  /**
   * Tests that if we readStringRequireUtf8 invalid UTF-8 bytes, an InvalidProtocolBufferException
   * is thrown.
   */
  public void testReadStringRequireUtf8InvalidUtf8() throws Exception {
    ByteString.Output rawOutput = ByteString.newOutput();
    CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);

    int tag = WireFormat.makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED);
    output.writeRawVarint32(tag);
    output.writeRawVarint32(1);
    output.writeRawBytes(new byte[] {(byte) 0x80});
    output.flush();

    CodedInputStream input = rawOutput.toByteString().newCodedInput();
    assertEquals(tag, input.readTag());
    try {
      input.readStringRequireUtf8();
      fail("Expected invalid UTF-8 exception.");
    } catch (InvalidProtocolBufferException exception) {
      assertEquals("Protocol message had invalid UTF-8.", exception.getMessage());
    }
  }
Пример #12
0
  public void testReadMaliciouslyLargeBlob() throws Exception {
    ByteString.Output rawOutput = ByteString.newOutput();
    CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);

    int tag = WireFormat.makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED);
    output.writeRawVarint32(tag);
    output.writeRawVarint32(0x7FFFFFFF);
    output.writeRawBytes(new byte[32]); // Pad with a few random bytes.
    output.flush();

    CodedInputStream input = rawOutput.toByteString().newCodedInput();
    assertEquals(tag, input.readTag());

    try {
      input.readBytes();
      fail("Should have thrown an exception!");
    } catch (InvalidProtocolBufferException e) {
      // success.
    }
  }
Пример #13
0
 /**
  * Read an Object or an Enum.
  *
  * @param length the actual length of the nested object or -1 if the length should be read from
  *     the stream
  */
 private <A> A readNestedObject(
     FieldDescriptor fd, Class<A> clazz, RawProtoStreamReader in, int length) throws IOException {
   BaseMarshallerDelegate<A> marshallerDelegate = ctx.getMarshallerDelegate(clazz);
   A a;
   if (fd.getType() == Type.GROUP) {
     a = marshallerDelegate.unmarshall(fd, this, in);
     in.checkLastTagWas(WireFormat.makeTag(fd.getNumber(), WireFormat.WIRETYPE_END_GROUP));
   } else if (fd.getType() == Type.MESSAGE) {
     if (length < 0) {
       length = in.readRawVarint32();
     }
     int oldLimit = in.pushLimit(length);
     a = marshallerDelegate.unmarshall(fd, this, in);
     in.checkLastTagWas(0);
     in.popLimit(oldLimit);
   } else {
     throw new IllegalArgumentException(
         "Declared field type is not a message or an enum : " + fd.getFullName());
   }
   return a;
 }
Пример #14
0
  @Override
  public <E, C extends Collection<? super E>> C readCollection(
      String fieldName, C collection, Class<E> elementClass) throws IOException {
    final FieldDescriptor fd = messageContext.marshallerDelegate.getFieldByName(fieldName);
    checkFieldRead(fd, true);

    if (primitiveTypes.contains(fd.getType())) {
      readPrimitiveCollection(fd, (Collection<Object>) collection, elementClass);
      return collection;
    }

    // todo validate type is compatible with readCollection
    final int expectedTag = WireFormat.makeTag(fd.getNumber(), fd.getType().getWireType());

    while (true) {
      Object o = messageContext.unknownFieldSet.consumeTag(expectedTag);
      if (o == null) {
        break;
      }
      byte[] byteArray = (byte[]) o;
      RawProtoStreamReader in = RawProtoStreamReaderImpl.newInstance(byteArray);
      collection.add(readNestedObject(fd, elementClass, in, byteArray.length));
    }

    while (true) {
      int tag = messageContext.in.readTag();
      if (tag == 0) {
        break;
      }
      if (tag == expectedTag) {
        collection.add(readNestedObject(fd, elementClass, messageContext.in, -1));
      } else {
        messageContext.unknownFieldSet.readSingleField(tag, messageContext.in);
      }
    }
    return collection;
  }
Пример #15
0
  public void testReadStringRequireUtf8() throws Exception {
    String lorem = "Lorem ipsum dolor sit amet ";
    StringBuilder builder = new StringBuilder();
    for (int i = 0; i < 4096; i += lorem.length()) {
      builder.append(lorem);
    }
    lorem = builder.toString().substring(0, 4096);
    byte[] bytes = lorem.getBytes("UTF-8");
    ByteString.Output rawOutput = ByteString.newOutput();
    CodedOutputStream output = CodedOutputStream.newInstance(rawOutput, bytes.length);

    int tag = WireFormat.makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED);
    output.writeRawVarint32(tag);
    output.writeRawVarint32(bytes.length);
    output.writeRawBytes(bytes);
    output.flush();

    CodedInputStream input =
        CodedInputStream.newInstance(
            new ByteArrayInputStream(rawOutput.toByteString().toByteArray()));
    assertEquals(tag, input.readTag());
    String text = input.readStringRequireUtf8();
    assertEquals(lorem, text);
  }
Пример #16
0
 /** Compute the number of bytes that would be needed to encode a tag. */
 public static int computeTagSize(int fieldNumber) {
   return computeRawVarint32Size(WireFormat.makeTag(fieldNumber, 0));
 }
Пример #17
0
 /** Encode and write a tag. */
 public void writeTag(int fieldNumber, int wireType) {
   writeRawVarint32(WireFormat.makeTag(fieldNumber, wireType));
 }
Пример #18
0
  private void readPrimitiveCollection(
      FieldDescriptor fd, Collection<? super Object> collection, Class elementClass)
      throws IOException {
    final int expectedTag = WireFormat.makeTag(fd.getNumber(), fd.getType().getWireType());
    Type type = fd.getType();

    while (true) {
      Object o = messageContext.unknownFieldSet.consumeTag(expectedTag);
      if (o == null) {
        break;
      }
      collection.add(
          convertWireTypeToJavaType(type, o)); // todo check that (o.getClass() == elementClass)
    }

    while (true) {
      int tag = messageContext.in.readTag();
      if (tag == 0) {
        break;
      }
      if (tag == expectedTag) {
        Object value;
        switch (type) {
          case DOUBLE:
            value = messageContext.in.readDouble();
            break;
          case FLOAT:
            value = messageContext.in.readFloat();
            break;
          case BOOL:
            value = messageContext.in.readBool();
            break;
          case STRING:
            value = messageContext.in.readString();
            break;
          case BYTES:
            value = messageContext.in.readByteArray();
            break;
          case INT64:
            value = messageContext.in.readInt64();
            break;
          case UINT64:
            value = messageContext.in.readUInt64();
            break;
          case FIXED64:
            value = messageContext.in.readFixed64();
            break;
          case SFIXED64:
            value = messageContext.in.readSFixed64();
            break;
          case SINT64:
            value = messageContext.in.readSInt64();
            break;
          case INT32:
            value = messageContext.in.readInt32();
            break;
          case FIXED32:
            value = messageContext.in.readFixed32();
            break;
          case UINT32:
            value = messageContext.in.readUInt32();
            break;
          case SFIXED32:
            value = messageContext.in.readSFixed32();
            break;
          case SINT32:
            value = messageContext.in.readSInt32();
            break;
          default:
            throw new IllegalStateException("Unexpected field type : " + type);
        }
        collection.add(value);
      } else {
        messageContext.unknownFieldSet.readSingleField(tag, messageContext.in);
      }
    }
  }
Пример #19
0
  private Object readPrimitive(String fieldName, JavaType javaType) throws IOException {
    final FieldDescriptor fd = messageContext.marshallerDelegate.getFieldByName(fieldName);
    final Type type = fd.getType();
    if (type == Type.ENUM || type == Type.GROUP || type == Type.MESSAGE) {
      throw new IllegalArgumentException(
          "Declared field type is not a primitive : " + fd.getFullName());
    }
    if (fd.getJavaType() != javaType) {
      throw new IllegalArgumentException(
          "Declared field type is not of the expected type : " + fd.getFullName());
    }
    checkFieldRead(fd, false);
    final int expectedTag = WireFormat.makeTag(fd.getNumber(), type.getWireType());

    Object o = messageContext.unknownFieldSet.consumeTag(expectedTag);
    if (o != null) {
      return convertWireTypeToJavaType(type, o);
    }

    RawProtoStreamReader in = messageContext.in;
    while (true) {
      int tag = in.readTag();
      if (tag == 0) {
        break;
      }
      if (tag == expectedTag) {
        switch (type) {
          case DOUBLE:
            return in.readDouble();
          case FLOAT:
            return in.readFloat();
          case BOOL:
            return in.readBool();
          case STRING:
            return in.readString();
          case BYTES:
            return in.readByteArray();
          case INT32:
            return in.readInt32();
          case SFIXED32:
            return in.readSFixed32();
          case FIXED32:
            return in.readFixed32();
          case UINT32:
            return in.readUInt32();
          case SINT32:
            return in.readSInt32();
          case INT64:
            return in.readInt64();
          case UINT64:
            return in.readUInt64();
          case FIXED64:
            return in.readFixed64();
          case SFIXED64:
            return in.readSFixed64();
          case SINT64:
            return in.readSInt64();
          default:
            throw new IOException("Unexpected field type : " + type);
        }
      }
      messageContext.unknownFieldSet.readSingleField(tag, in);
    }

    if (fd.hasDefaultValue()) {
      return fd.getDefaultValue();
    }

    if (fd.isRequired()) {
      throw new IOException(
          "Field " + fd.getFullName() + " is required but is not present in the stream");
    }

    return null;
  }