164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// Protocol Buffers - Google's data interchange format
264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// Copyright 2013 Google Inc.  All rights reserved.
364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// http://code.google.com/p/protobuf/
464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci//
564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// Redistribution and use in source and binary forms, with or without
664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// modification, are permitted provided that the following conditions are
764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// met:
864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci//
964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci//     * Redistributions of source code must retain the above copyright
1064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// notice, this list of conditions and the following disclaimer.
1164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci//     * Redistributions in binary form must reproduce the above
1264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// copyright notice, this list of conditions and the following disclaimer
1364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// in the documentation and/or other materials provided with the
1464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// distribution.
1564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci//     * Neither the name of Google Inc. nor the names of its
1664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// contributors may be used to endorse or promote products derived from
1764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// this software without specific prior written permission.
1864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci//
1964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
3164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazcipackage com.google.protobuf.nano;
3264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
3364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazciimport java.io.IOException;
340e055f079f53b07de3705838a7b4742ce56839f8Brian Duffimport java.util.ArrayList;
350e055f079f53b07de3705838a7b4742ce56839f8Brian Duffimport java.util.Iterator;
360e055f079f53b07de3705838a7b4742ce56839f8Brian Duffimport java.util.List;
3764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
3864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci/**
3964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * This class is used internally by the Protocol Buffer library and generated
4064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * message implementations.  It is public only because those generated messages
4164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * do not reside in the {@code protobuf} package.  Others should not use this
4264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * class directly.
4364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci *
4464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * This class contains constants and helper functions useful for dealing with
4564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * the Protocol Buffer wire format.
4664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci *
4764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci * @author kenton@google.com Kenton Varda
4864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci */
4964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazcipublic final class WireFormatNano {
5064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  // Do not allow instantiation.
5164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  private WireFormatNano() {}
5264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
5364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  static final int WIRETYPE_VARINT           = 0;
5464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  static final int WIRETYPE_FIXED64          = 1;
5564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  static final int WIRETYPE_LENGTH_DELIMITED = 2;
5664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  static final int WIRETYPE_START_GROUP      = 3;
5764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  static final int WIRETYPE_END_GROUP        = 4;
5864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  static final int WIRETYPE_FIXED32          = 5;
5964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
6064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  static final int TAG_TYPE_BITS = 3;
6164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  static final int TAG_TYPE_MASK = (1 << TAG_TYPE_BITS) - 1;
6264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
6364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  /** Given a tag value, determines the wire type (the lower 3 bits). */
6464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  static int getTagWireType(final int tag) {
6564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    return tag & TAG_TYPE_MASK;
6664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  }
6764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
6864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  /** Given a tag value, determines the field number (the upper 29 bits). */
6964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  public static int getTagFieldNumber(final int tag) {
7064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    return tag >>> TAG_TYPE_BITS;
7164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  }
7264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
7364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  /** Makes a tag value given a field number and wire type. */
7464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  static int makeTag(final int fieldNumber, final int wireType) {
7564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    return (fieldNumber << TAG_TYPE_BITS) | wireType;
7664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  }
7764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
7864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  // Field numbers for feilds in MessageSet wire format.
7964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  static final int MESSAGE_SET_ITEM    = 1;
8064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  static final int MESSAGE_SET_TYPE_ID = 2;
8164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  static final int MESSAGE_SET_MESSAGE = 3;
8264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
8364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  // Tag numbers.
8464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  static final int MESSAGE_SET_ITEM_TAG =
8564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    makeTag(MESSAGE_SET_ITEM, WIRETYPE_START_GROUP);
8664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  static final int MESSAGE_SET_ITEM_END_TAG =
8764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    makeTag(MESSAGE_SET_ITEM, WIRETYPE_END_GROUP);
8864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  static final int MESSAGE_SET_TYPE_ID_TAG =
8964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    makeTag(MESSAGE_SET_TYPE_ID, WIRETYPE_VARINT);
9064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  static final int MESSAGE_SET_MESSAGE_TAG =
9164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    makeTag(MESSAGE_SET_MESSAGE, WIRETYPE_LENGTH_DELIMITED);
9264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
9364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  public static final int EMPTY_INT_ARRAY[] = {};
9464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  public static final long EMPTY_LONG_ARRAY[] = {};
9564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  public static final float EMPTY_FLOAT_ARRAY[] = {};
9664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  public static final double EMPTY_DOUBLE_ARRAY[] = {};
9764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  public static final boolean EMPTY_BOOLEAN_ARRAY[] = {};
9864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  public static final String EMPTY_STRING_ARRAY[] = {};
9964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  public static final byte[] EMPTY_BYTES_ARRAY[] = {};
10064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  public static final byte[] EMPTY_BYTES = {};
10164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
10264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  /**
1030e055f079f53b07de3705838a7b4742ce56839f8Brian Duff   * Parses an unknown field. This implementation skips the field.
1040e055f079f53b07de3705838a7b4742ce56839f8Brian Duff   *
1050e055f079f53b07de3705838a7b4742ce56839f8Brian Duff   * <p>Generated messages will call this for unknown fields if the store_unknown_fields
1060e055f079f53b07de3705838a7b4742ce56839f8Brian Duff   * option is off.
1070e055f079f53b07de3705838a7b4742ce56839f8Brian Duff   *
1080e055f079f53b07de3705838a7b4742ce56839f8Brian Duff   * @return {@literal true} unless the tag is an end-group tag.
10964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   */
11064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  public static boolean parseUnknownField(
11164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      final CodedInputByteBufferNano input,
11264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      final int tag) throws IOException {
11364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    return input.skipField(tag);
11464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  }
11564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci
11664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  /**
1170e055f079f53b07de3705838a7b4742ce56839f8Brian Duff   * Stores the binary data of an unknown field.
1180e055f079f53b07de3705838a7b4742ce56839f8Brian Duff   *
1190e055f079f53b07de3705838a7b4742ce56839f8Brian Duff   * <p>Generated messages will call this for unknown fields if the store_unknown_fields
1200e055f079f53b07de3705838a7b4742ce56839f8Brian Duff   * option is on.
1210e055f079f53b07de3705838a7b4742ce56839f8Brian Duff   *
1220e055f079f53b07de3705838a7b4742ce56839f8Brian Duff   * @param data a Collection in which to store the data.
1230e055f079f53b07de3705838a7b4742ce56839f8Brian Duff   * @param input the input buffer.
1240e055f079f53b07de3705838a7b4742ce56839f8Brian Duff   * @param tag the tag of the field.
1250e055f079f53b07de3705838a7b4742ce56839f8Brian Duff
1260e055f079f53b07de3705838a7b4742ce56839f8Brian Duff   * @return {@literal true} unless the tag is an end-group tag.
1270e055f079f53b07de3705838a7b4742ce56839f8Brian Duff   */
1280e055f079f53b07de3705838a7b4742ce56839f8Brian Duff  public static boolean storeUnknownField(
1290e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      final List<UnknownFieldData> data,
1300e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      final CodedInputByteBufferNano input,
1310e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      final int tag) throws IOException {
1320e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    int startPos = input.getPosition();
1330e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    boolean skip = input.skipField(tag);
1340e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    int endPos = input.getPosition();
1350e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    byte[] bytes = input.getData(startPos, endPos - startPos);
1360e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    data.add(new UnknownFieldData(tag, bytes));
1370e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    return skip;
1380e055f079f53b07de3705838a7b4742ce56839f8Brian Duff  }
1390e055f079f53b07de3705838a7b4742ce56839f8Brian Duff
1400e055f079f53b07de3705838a7b4742ce56839f8Brian Duff  /**
14164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * Computes the array length of a repeated field. We assume that in the common case repeated
14264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * fields are contiguously serialized but we still correctly handle interspersed values of a
14364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * repeated field (but with extra allocations).
14464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   *
14564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * Rewinds to current input position before returning.
14664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   *
14764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * @param input stream input, pointing to the byte after the first tag
14864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * @param tag repeated field tag just read
14964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * @return length of array
15064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   * @throws IOException
15164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci   */
15264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  public static final int getRepeatedFieldArrayLength(
15364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      final CodedInputByteBufferNano input,
15464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      final int tag) throws IOException {
15564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    int arrayLength = 1;
15664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    int startPos = input.getPosition();
15764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    input.skipField(tag);
15864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    while (input.getBytesUntilLimit() > 0) {
15964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      int thisTag = input.readTag();
16064d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      if (thisTag != tag) {
16164d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci        break;
16264d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      }
16364d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      input.skipField(tag);
16464d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci      arrayLength++;
16564d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    }
16664d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    input.rewindToPosition(startPos);
16764d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci    return arrayLength;
16864d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci  }
1690e055f079f53b07de3705838a7b4742ce56839f8Brian Duff
1700e055f079f53b07de3705838a7b4742ce56839f8Brian Duff  /**
1710e055f079f53b07de3705838a7b4742ce56839f8Brian Duff   * Decodes the value of an extension.
1720e055f079f53b07de3705838a7b4742ce56839f8Brian Duff   */
1730e055f079f53b07de3705838a7b4742ce56839f8Brian Duff  public static <T> T getExtension(Extension<T> extension, List<UnknownFieldData> unknownFields) {
1740e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    if (unknownFields == null) {
1750e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      return null;
1760e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    }
1770e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    List<UnknownFieldData> dataForField = new ArrayList<UnknownFieldData>();
1780e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    for (UnknownFieldData data : unknownFields) {
1790e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      if (getTagFieldNumber(data.tag) == extension.fieldNumber) {
1800e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        dataForField.add(data);
1810e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      }
1820e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    }
1830e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    if (dataForField.isEmpty()) {
1840e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      return null;
1850e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    }
1860e055f079f53b07de3705838a7b4742ce56839f8Brian Duff
1870e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    if (extension.isRepeatedField) {
1880e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      List<Object> result = new ArrayList<Object>(dataForField.size());
1890e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      for (UnknownFieldData data : dataForField) {
1900e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        result.add(readData(extension.fieldType, data.bytes));
1910e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      }
1920e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      return extension.listType.cast(result);
1930e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    }
1940e055f079f53b07de3705838a7b4742ce56839f8Brian Duff
1950e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    // Normal fields. Note that the protobuf docs require us to handle multiple instances
1960e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    // of the same field even for fields that are not repeated.
1970e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    UnknownFieldData lastData = dataForField.get(dataForField.size() - 1);
1980e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    return readData(extension.fieldType, lastData.bytes);
1990e055f079f53b07de3705838a7b4742ce56839f8Brian Duff  }
2000e055f079f53b07de3705838a7b4742ce56839f8Brian Duff
2010e055f079f53b07de3705838a7b4742ce56839f8Brian Duff  /**
2020e055f079f53b07de3705838a7b4742ce56839f8Brian Duff   * Reads (extension) data of the specified type from the specified byte array.
2030e055f079f53b07de3705838a7b4742ce56839f8Brian Duff   *
2040e055f079f53b07de3705838a7b4742ce56839f8Brian Duff   * @throws IllegalArgumentException if an error occurs while reading the data.
2050e055f079f53b07de3705838a7b4742ce56839f8Brian Duff   */
2060e055f079f53b07de3705838a7b4742ce56839f8Brian Duff  private static <T> T readData(Class<T> clazz, byte[] data) {
2070e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    if (data.length == 0) {
2080e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      return null;
2090e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    }
2100e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    CodedInputByteBufferNano buffer = CodedInputByteBufferNano.newInstance(data);
2110e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    try {
2120e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      if (clazz == String.class) {
2130e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        return clazz.cast(buffer.readString());
2140e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      } else if (clazz == Integer.class) {
2150e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        return clazz.cast(buffer.readInt32());
2160e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      } else if (clazz == Long.class) {
2170e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        return clazz.cast(buffer.readInt64());
2180e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      } else if (clazz == Boolean.class) {
2190e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        return clazz.cast(buffer.readBool());
2200e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      } else if (clazz == Float.class) {
2210e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        return clazz.cast(buffer.readFloat());
2220e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      } else if (clazz == Double.class) {
2230e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        return clazz.cast(buffer.readDouble());
2240e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      } else if (clazz == byte[].class) {
2250e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        return clazz.cast(buffer.readBytes());
2260e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      } else if (MessageNano.class.isAssignableFrom(clazz)) {
2270e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        try {
2280e055f079f53b07de3705838a7b4742ce56839f8Brian Duff          MessageNano message = (MessageNano) clazz.newInstance();
2290e055f079f53b07de3705838a7b4742ce56839f8Brian Duff          buffer.readMessage(message);
2300e055f079f53b07de3705838a7b4742ce56839f8Brian Duff          return clazz.cast(message);
2310e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        } catch (IllegalAccessException e) {
2320e055f079f53b07de3705838a7b4742ce56839f8Brian Duff          throw new IllegalArgumentException("Error creating instance of class " + clazz, e);
2330e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        } catch (InstantiationException e) {
2340e055f079f53b07de3705838a7b4742ce56839f8Brian Duff          throw new IllegalArgumentException("Error creating instance of class " + clazz, e);
2350e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        }
2360e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      } else {
2370e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        throw new IllegalArgumentException("Unhandled extension field type: " + clazz);
2380e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      }
2390e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    } catch (IOException e) {
2400e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      throw new IllegalArgumentException("Error reading extension field", e);
2410e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    }
2420e055f079f53b07de3705838a7b4742ce56839f8Brian Duff  }
2430e055f079f53b07de3705838a7b4742ce56839f8Brian Duff
2440e055f079f53b07de3705838a7b4742ce56839f8Brian Duff  public static <T> void setExtension(Extension<T> extension, T value,
2450e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      List<UnknownFieldData> unknownFields) {
2460e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    // First, remove all unknown fields with this tag.
2470e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    for (Iterator<UnknownFieldData> i = unknownFields.iterator(); i.hasNext();) {
2480e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      UnknownFieldData data = i.next();
2490e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      if (extension.fieldNumber == getTagFieldNumber(data.tag)) {
2500e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        i.remove();
2510e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      }
2520e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    }
2530e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    if (value == null) {
2540e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      return;
2550e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    }
2560e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    // Repeated field.
2570e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    if (value instanceof List) {
2580e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      for (Object item : (List<?>) value) {
2590e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        unknownFields.add(write(extension.fieldNumber, item));
2600e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      }
2610e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    } else {
2620e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      unknownFields.add(write(extension.fieldNumber, value));
2630e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    }
2640e055f079f53b07de3705838a7b4742ce56839f8Brian Duff  }
2650e055f079f53b07de3705838a7b4742ce56839f8Brian Duff
2660e055f079f53b07de3705838a7b4742ce56839f8Brian Duff  /**
2670e055f079f53b07de3705838a7b4742ce56839f8Brian Duff   * Writes extension data and returns an {@link UnknownFieldData} containing
2680e055f079f53b07de3705838a7b4742ce56839f8Brian Duff   * bytes and a tag.
2690e055f079f53b07de3705838a7b4742ce56839f8Brian Duff   *
2700e055f079f53b07de3705838a7b4742ce56839f8Brian Duff   * @throws IllegalArgumentException if an error occurs while writing.
2710e055f079f53b07de3705838a7b4742ce56839f8Brian Duff   */
2720e055f079f53b07de3705838a7b4742ce56839f8Brian Duff  private static UnknownFieldData write(int fieldNumber, Object object) {
2730e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    byte[] data;
2740e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    int tag;
2750e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    Class<?> clazz = object.getClass();
2760e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    try {
2770e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      if (clazz == String.class) {
2780e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        String str = (String) object;
2790e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        data = new byte[CodedOutputByteBufferNano.computeStringSizeNoTag(str)];
2800e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        CodedOutputByteBufferNano.newInstance(data).writeStringNoTag(str);
2810e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        tag = makeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
2820e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      } else if (clazz == Integer.class) {
2830e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        Integer integer = (Integer) object;
2840e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        data = new byte[CodedOutputByteBufferNano.computeInt32SizeNoTag(integer)];
2850e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        CodedOutputByteBufferNano.newInstance(data).writeInt32NoTag(integer);
2860e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        tag = makeTag(fieldNumber, WIRETYPE_VARINT);
2870e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      } else if (clazz == Long.class) {
2880e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        Long longValue = (Long) object;
2890e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        data = new byte[CodedOutputByteBufferNano.computeInt64SizeNoTag(longValue)];
2900e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        CodedOutputByteBufferNano.newInstance(data).writeInt64NoTag(longValue);
2910e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        tag = makeTag(fieldNumber, WIRETYPE_VARINT);
2920e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      } else if (clazz == Boolean.class) {
2930e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        Boolean boolValue = (Boolean) object;
2940e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        data = new byte[CodedOutputByteBufferNano.computeBoolSizeNoTag(boolValue)];
2950e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        CodedOutputByteBufferNano.newInstance(data).writeBoolNoTag(boolValue);
2960e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        tag = makeTag(fieldNumber, WIRETYPE_VARINT);
2970e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      } else if (clazz == Float.class) {
2980e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        Float floatValue = (Float) object;
2990e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        data = new byte[CodedOutputByteBufferNano.computeFloatSizeNoTag(floatValue)];
3000e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        CodedOutputByteBufferNano.newInstance(data).writeFloatNoTag(floatValue);
3010e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        tag = makeTag(fieldNumber, WIRETYPE_FIXED32);
3020e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      } else if (clazz == Double.class) {
3030e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        Double doubleValue = (Double) object;
3040e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        data = new byte[CodedOutputByteBufferNano.computeDoubleSizeNoTag(doubleValue)];
3050e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        CodedOutputByteBufferNano.newInstance(data).writeDoubleNoTag(doubleValue);
3060e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        tag = makeTag(fieldNumber, WIRETYPE_FIXED64);
3070e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      } else if (clazz == byte[].class) {
3080e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        byte[] byteArrayValue = (byte[]) object;
3090e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        data = new byte[CodedOutputByteBufferNano.computeByteArraySizeNoTag(byteArrayValue)];
3100e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        CodedOutputByteBufferNano.newInstance(data).writeByteArrayNoTag(byteArrayValue);
3110e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        tag = makeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
3120e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      } else if (MessageNano.class.isAssignableFrom(clazz)) {
3130e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        MessageNano messageValue = (MessageNano) object;
3140e055f079f53b07de3705838a7b4742ce56839f8Brian Duff
3150e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        int messageSize = messageValue.getSerializedSize();
3160e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        int delimiterSize = CodedOutputByteBufferNano.computeRawVarint32Size(messageSize);
3170e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        data = new byte[messageSize + delimiterSize];
3180e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        CodedOutputByteBufferNano buffer = CodedOutputByteBufferNano.newInstance(data);
3190e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        buffer.writeRawVarint32(messageSize);
3200e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        buffer.writeRawBytes(MessageNano.toByteArray(messageValue));
3210e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        tag = makeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
3220e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      } else {
3230e055f079f53b07de3705838a7b4742ce56839f8Brian Duff        throw new IllegalArgumentException("Unhandled extension field type: " + clazz);
3240e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      }
3250e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    } catch (IOException e) {
3260e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      throw new IllegalArgumentException(e);
3270e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    }
3280e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    return new UnknownFieldData(tag, data);
3290e055f079f53b07de3705838a7b4742ce56839f8Brian Duff  }
3300e055f079f53b07de3705838a7b4742ce56839f8Brian Duff
3310e055f079f53b07de3705838a7b4742ce56839f8Brian Duff  /**
3320e055f079f53b07de3705838a7b4742ce56839f8Brian Duff   * Given a set of unknown field data, compute the wire size.
3330e055f079f53b07de3705838a7b4742ce56839f8Brian Duff   */
3340e055f079f53b07de3705838a7b4742ce56839f8Brian Duff  public static int computeWireSize(List<UnknownFieldData> unknownFields) {
3350e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    if (unknownFields == null) {
3360e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      return 0;
3370e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    }
3380e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    int size = 0;
3390e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    for (UnknownFieldData unknownField : unknownFields) {
3400e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      size += CodedOutputByteBufferNano.computeRawVarint32Size(unknownField.tag);
3410e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      size += unknownField.bytes.length;
3420e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    }
3430e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    return size;
3440e055f079f53b07de3705838a7b4742ce56839f8Brian Duff  }
3450e055f079f53b07de3705838a7b4742ce56839f8Brian Duff
3460e055f079f53b07de3705838a7b4742ce56839f8Brian Duff  /**
3470e055f079f53b07de3705838a7b4742ce56839f8Brian Duff   * Write unknown fields.
3480e055f079f53b07de3705838a7b4742ce56839f8Brian Duff   */
3490e055f079f53b07de3705838a7b4742ce56839f8Brian Duff  public static void writeUnknownFields(List<UnknownFieldData> unknownFields,
3500e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      CodedOutputByteBufferNano outBuffer) throws IOException {
3510e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    if (unknownFields == null) {
3520e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      return;
3530e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    }
3540e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    for (UnknownFieldData data : unknownFields) {
3550e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      outBuffer.writeTag(getTagFieldNumber(data.tag), getTagWireType(data.tag));
3560e055f079f53b07de3705838a7b4742ce56839f8Brian Duff      outBuffer.writeRawBytes(data.bytes);
3570e055f079f53b07de3705838a7b4742ce56839f8Brian Duff    }
3580e055f079f53b07de3705838a7b4742ce56839f8Brian Duff  }
35964d8d8f89050c5ada85341f967af391f4716a7cbUlas Kirazci}
360