|  | @@ -30,85 +30,659 @@
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  package com.google.protobuf.nano;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -import java.lang.reflect.ParameterizedType;
 | 
	
		
			
				|  |  | -import java.lang.reflect.Type;
 | 
	
		
			
				|  |  | +import java.io.IOException;
 | 
	
		
			
				|  |  | +import java.lang.reflect.Array;
 | 
	
		
			
				|  |  | +import java.util.ArrayList;
 | 
	
		
			
				|  |  |  import java.util.List;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /**
 | 
	
		
			
				|  |  |   * Represents an extension.
 | 
	
		
			
				|  |  |   *
 | 
	
		
			
				|  |  |   * @author bduff@google.com (Brian Duff)
 | 
	
		
			
				|  |  | - * @param <T> the type of the extension.
 | 
	
		
			
				|  |  | + * @author maxtroy@google.com (Max Cai)
 | 
	
		
			
				|  |  | + * @param <M> the type of the extendable message this extension is for.
 | 
	
		
			
				|  |  | + * @param <T> the Java type of the extension; see {@link #clazz}.
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  | -public class Extension<T> {
 | 
	
		
			
				|  |  | -  public final int fieldNumber;
 | 
	
		
			
				|  |  | -  public boolean isRepeatedField;
 | 
	
		
			
				|  |  | -  public Class<T> fieldType;
 | 
	
		
			
				|  |  | -  public Class<T> listType;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  private Extension(int fieldNumber, TypeLiteral<T> type) {
 | 
	
		
			
				|  |  | -    this.fieldNumber = fieldNumber;
 | 
	
		
			
				|  |  | -    isRepeatedField = type.isList();
 | 
	
		
			
				|  |  | -    fieldType = type.getTargetClass();
 | 
	
		
			
				|  |  | -    listType = isRepeatedField ? type.getListType() : null;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  /**
 | 
	
		
			
				|  |  | -   * Creates a new instance of {@code Extension} for the specified {@code fieldNumber} and
 | 
	
		
			
				|  |  | -   * {@code type}.
 | 
	
		
			
				|  |  | -   */
 | 
	
		
			
				|  |  | -  public static <T> Extension<T> create(int fieldNumber, TypeLiteral<T> type) {
 | 
	
		
			
				|  |  | -    return new Extension<T>(fieldNumber, type);
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  /**
 | 
	
		
			
				|  |  | -   * Creates a new instance of {@code Extension} for the specified {@code fieldNumber} and
 | 
	
		
			
				|  |  | -   * {@code type}. This version is used for repeated fields.
 | 
	
		
			
				|  |  | -   */
 | 
	
		
			
				|  |  | -  public static <T> Extension<List<T>> createRepeated(int fieldNumber, TypeLiteral<List<T>> type) {
 | 
	
		
			
				|  |  | -    return new Extension<List<T>>(fieldNumber, type);
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  /**
 | 
	
		
			
				|  |  | -   * Represents a generic type literal. We can't typesafely reference a
 | 
	
		
			
				|  |  | -   * Class<List<Foo>>.class in Java, so we use this instead.
 | 
	
		
			
				|  |  | -   * See: http://gafter.blogspot.com/2006/12/super-type-tokens.html
 | 
	
		
			
				|  |  | -   *
 | 
	
		
			
				|  |  | -   * <p>Somewhat specialized because we only ever have a Foo or a List<Foo>.
 | 
	
		
			
				|  |  | -   */
 | 
	
		
			
				|  |  | -  public static abstract class TypeLiteral<T> {
 | 
	
		
			
				|  |  | -    private final Type type;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    protected TypeLiteral() {
 | 
	
		
			
				|  |  | -      Type superclass = getClass().getGenericSuperclass();
 | 
	
		
			
				|  |  | -      if (superclass instanceof Class) {
 | 
	
		
			
				|  |  | -        throw new RuntimeException("Missing type parameter");
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -      this.type = ((ParameterizedType) superclass).getActualTypeArguments()[0];
 | 
	
		
			
				|  |  | +public class Extension<M extends ExtendableMessageNano<M>, T> {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /*
 | 
	
		
			
				|  |  | +     * Because we typically only define message-typed extensions, the Extension class hierarchy is
 | 
	
		
			
				|  |  | +     * designed as follows, to allow a big amount of code in this file to be removed by ProGuard:
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     *            Extension          // ready to use for message/group typed extensions
 | 
	
		
			
				|  |  | +     *                Δ
 | 
	
		
			
				|  |  | +     *                |
 | 
	
		
			
				|  |  | +     *       PrimitiveExtension      // for primitive/enum typed extensions
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public static final int TYPE_DOUBLE   = 1;
 | 
	
		
			
				|  |  | +    public static final int TYPE_FLOAT    = 2;
 | 
	
		
			
				|  |  | +    public static final int TYPE_INT64    = 3;
 | 
	
		
			
				|  |  | +    public static final int TYPE_UINT64   = 4;
 | 
	
		
			
				|  |  | +    public static final int TYPE_INT32    = 5;
 | 
	
		
			
				|  |  | +    public static final int TYPE_FIXED64  = 6;
 | 
	
		
			
				|  |  | +    public static final int TYPE_FIXED32  = 7;
 | 
	
		
			
				|  |  | +    public static final int TYPE_BOOL     = 8;
 | 
	
		
			
				|  |  | +    public static final int TYPE_STRING   = 9;
 | 
	
		
			
				|  |  | +    public static final int TYPE_GROUP    = 10;
 | 
	
		
			
				|  |  | +    public static final int TYPE_MESSAGE  = 11;
 | 
	
		
			
				|  |  | +    public static final int TYPE_BYTES    = 12;
 | 
	
		
			
				|  |  | +    public static final int TYPE_UINT32   = 13;
 | 
	
		
			
				|  |  | +    public static final int TYPE_ENUM     = 14;
 | 
	
		
			
				|  |  | +    public static final int TYPE_SFIXED32 = 15;
 | 
	
		
			
				|  |  | +    public static final int TYPE_SFIXED64 = 16;
 | 
	
		
			
				|  |  | +    public static final int TYPE_SINT32   = 17;
 | 
	
		
			
				|  |  | +    public static final int TYPE_SINT64   = 18;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * Creates an {@code Extension} of the given message type and tag number.
 | 
	
		
			
				|  |  | +     * Should be used by the generated code only.
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param type {@link #TYPE_MESSAGE} or {@link #TYPE_GROUP}
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public static <M extends ExtendableMessageNano<M>, T extends MessageNano>
 | 
	
		
			
				|  |  | +            Extension<M, T> createMessageTyped(int type, Class<T> clazz, int tag) {
 | 
	
		
			
				|  |  | +        return new Extension<M, T>(type, clazz, tag, false);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * Creates a repeated {@code Extension} of the given message type and tag number.
 | 
	
		
			
				|  |  | +     * Should be used by the generated code only.
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param type {@link #TYPE_MESSAGE} or {@link #TYPE_GROUP}
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public static <M extends ExtendableMessageNano<M>, T extends MessageNano>
 | 
	
		
			
				|  |  | +            Extension<M, T[]> createRepeatedMessageTyped(int type, Class<T[]> clazz, int tag) {
 | 
	
		
			
				|  |  | +        return new Extension<M, T[]>(type, clazz, tag, true);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * Creates an {@code Extension} of the given primitive type and tag number.
 | 
	
		
			
				|  |  | +     * Should be used by the generated code only.
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param type one of {@code TYPE_*}, except {@link #TYPE_MESSAGE} and {@link #TYPE_GROUP}
 | 
	
		
			
				|  |  | +     * @param clazz the boxed Java type of this extension
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public static <M extends ExtendableMessageNano<M>, T>
 | 
	
		
			
				|  |  | +            Extension<M, T> createPrimitiveTyped(int type, Class<T> clazz, int tag) {
 | 
	
		
			
				|  |  | +        return new PrimitiveExtension<M, T>(type, clazz, tag, false, 0, 0);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * Creates a repeated {@code Extension} of the given primitive type and tag number.
 | 
	
		
			
				|  |  | +     * Should be used by the generated code only.
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param type one of {@code TYPE_*}, except {@link #TYPE_MESSAGE} and {@link #TYPE_GROUP}
 | 
	
		
			
				|  |  | +     * @param clazz the Java array type of this extension, with an unboxed component type
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public static <M extends ExtendableMessageNano<M>, T>
 | 
	
		
			
				|  |  | +            Extension<M, T> createRepeatedPrimitiveTyped(
 | 
	
		
			
				|  |  | +                    int type, Class<T> clazz, int tag, int nonPackedTag, int packedTag) {
 | 
	
		
			
				|  |  | +        return new PrimitiveExtension<M, T>(type, clazz, tag, true, nonPackedTag, packedTag);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * Protocol Buffer type of this extension; one of the {@code TYPE_} constants.
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    protected final int type;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * Java type of this extension. For a singular extension, this is the boxed Java type for the
 | 
	
		
			
				|  |  | +     * Protocol Buffer {@link #type}; for a repeated extension, this is an array type whose
 | 
	
		
			
				|  |  | +     * component type is the unboxed Java type for {@link #type}. For example, for a singular
 | 
	
		
			
				|  |  | +     * {@code int32}/{@link #TYPE_INT32} extension, this equals {@code Integer.class}; for a
 | 
	
		
			
				|  |  | +     * repeated {@code int32} extension, this equals {@code int[].class}.
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    protected final Class<T> clazz;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * Tag number of this extension.
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    protected final int tag;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * Whether this extension is repeated.
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    protected final boolean repeated;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private Extension(int type, Class<T> clazz, int tag, boolean repeated) {
 | 
	
		
			
				|  |  | +        this.type = type;
 | 
	
		
			
				|  |  | +        this.clazz = clazz;
 | 
	
		
			
				|  |  | +        this.tag = tag;
 | 
	
		
			
				|  |  | +        this.repeated = repeated;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    protected boolean isMatch(int unknownDataTag) {
 | 
	
		
			
				|  |  | +        // This implementation is for message/group extensions.
 | 
	
		
			
				|  |  | +        return unknownDataTag == tag;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * Returns the value of this extension stored in the given list of unknown fields, or
 | 
	
		
			
				|  |  | +     * {@code null} if no unknown fields matches this extension.
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    final T getValueFrom(List<UnknownFieldData> unknownFields) {
 | 
	
		
			
				|  |  | +        if (unknownFields == null) {
 | 
	
		
			
				|  |  | +            return null;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if (repeated) {
 | 
	
		
			
				|  |  | +            // For repeated extensions, read all matching unknown fields in their original order.
 | 
	
		
			
				|  |  | +            List<Object> resultList = new ArrayList<Object>();
 | 
	
		
			
				|  |  | +            for (int i = 0; i < unknownFields.size(); i++) {
 | 
	
		
			
				|  |  | +                UnknownFieldData data = unknownFields.get(i);
 | 
	
		
			
				|  |  | +                if (isMatch(data.tag) && data.bytes.length != 0) {
 | 
	
		
			
				|  |  | +                    readDataInto(data, resultList);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            int resultSize = resultList.size();
 | 
	
		
			
				|  |  | +            if (resultSize == 0) {
 | 
	
		
			
				|  |  | +                return null;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            T result = clazz.cast(Array.newInstance(clazz.getComponentType(), resultSize));
 | 
	
		
			
				|  |  | +            for (int i = 0; i < resultSize; i++) {
 | 
	
		
			
				|  |  | +                Array.set(result, i, resultList.get(i));
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            return result;
 | 
	
		
			
				|  |  | +        } else {
 | 
	
		
			
				|  |  | +            // For singular extensions, get the last piece of data stored under this extension.
 | 
	
		
			
				|  |  | +            UnknownFieldData lastData = null;
 | 
	
		
			
				|  |  | +            for (int i = unknownFields.size() - 1; lastData == null && i >= 0; i--) {
 | 
	
		
			
				|  |  | +                UnknownFieldData data = unknownFields.get(i);
 | 
	
		
			
				|  |  | +                if (isMatch(data.tag) && data.bytes.length != 0) {
 | 
	
		
			
				|  |  | +                    lastData = data;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if (lastData == null) {
 | 
	
		
			
				|  |  | +                return null;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            return clazz.cast(readData(CodedInputByteBufferNano.newInstance(lastData.bytes)));
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    protected Object readData(CodedInputByteBufferNano input) {
 | 
	
		
			
				|  |  | +        // This implementation is for message/group extensions.
 | 
	
		
			
				|  |  | +        Class<?> messageType = repeated ? clazz.getComponentType() : clazz;
 | 
	
		
			
				|  |  | +        try {
 | 
	
		
			
				|  |  | +            switch (type) {
 | 
	
		
			
				|  |  | +                case TYPE_GROUP:
 | 
	
		
			
				|  |  | +                    MessageNano group = (MessageNano) messageType.newInstance();
 | 
	
		
			
				|  |  | +                    input.readGroup(group, WireFormatNano.getTagFieldNumber(tag));
 | 
	
		
			
				|  |  | +                    return group;
 | 
	
		
			
				|  |  | +                case TYPE_MESSAGE:
 | 
	
		
			
				|  |  | +                    MessageNano message = (MessageNano) messageType.newInstance();
 | 
	
		
			
				|  |  | +                    input.readMessage(message);
 | 
	
		
			
				|  |  | +                    return message;
 | 
	
		
			
				|  |  | +                default:
 | 
	
		
			
				|  |  | +                    throw new IllegalArgumentException("Unknown type " + type);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        } catch (InstantiationException e) {
 | 
	
		
			
				|  |  | +            throw new IllegalArgumentException(
 | 
	
		
			
				|  |  | +                    "Error creating instance of class " + messageType, e);
 | 
	
		
			
				|  |  | +        } catch (IllegalAccessException e) {
 | 
	
		
			
				|  |  | +            throw new IllegalArgumentException(
 | 
	
		
			
				|  |  | +                    "Error creating instance of class " + messageType, e);
 | 
	
		
			
				|  |  | +        } catch (IOException e) {
 | 
	
		
			
				|  |  | +            throw new IllegalArgumentException("Error reading extension field", e);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    protected void readDataInto(UnknownFieldData data, List<Object> resultList) {
 | 
	
		
			
				|  |  | +        // This implementation is for message/group extensions.
 | 
	
		
			
				|  |  | +        resultList.add(readData(CodedInputByteBufferNano.newInstance(data.bytes)));
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      /**
 | 
	
		
			
				|  |  | -     * If the generic type is a list, returns {@code true}.
 | 
	
		
			
				|  |  | +     * Sets the value of this extension to the given list of unknown fields. This removes any
 | 
	
		
			
				|  |  | +     * previously stored data matching this extension.
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param value The value of this extension, or {@code null} to clear this extension from the
 | 
	
		
			
				|  |  | +     *     unknown fields.
 | 
	
		
			
				|  |  | +     * @return The same {@code unknownFields} list, or a new list storing the extension value if
 | 
	
		
			
				|  |  | +     *     the argument was null.
 | 
	
		
			
				|  |  |       */
 | 
	
		
			
				|  |  | -    private boolean isList() {
 | 
	
		
			
				|  |  | -      return type instanceof ParameterizedType;
 | 
	
		
			
				|  |  | +    final List<UnknownFieldData> setValueTo(T value, List<UnknownFieldData> unknownFields) {
 | 
	
		
			
				|  |  | +        if (unknownFields != null) {
 | 
	
		
			
				|  |  | +            // Delete all data matching this extension
 | 
	
		
			
				|  |  | +            for (int i = unknownFields.size() - 1; i >= 0; i--) {
 | 
	
		
			
				|  |  | +                if (isMatch(unknownFields.get(i).tag)) {
 | 
	
		
			
				|  |  | +                    unknownFields.remove(i);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if (value != null) {
 | 
	
		
			
				|  |  | +            if (unknownFields == null) {
 | 
	
		
			
				|  |  | +                unknownFields = new ArrayList<UnknownFieldData>();
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            if (repeated) {
 | 
	
		
			
				|  |  | +                writeDataInto(value, unknownFields);
 | 
	
		
			
				|  |  | +            } else {
 | 
	
		
			
				|  |  | +                unknownFields.add(writeData(value));
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // After deletion or no-op addition (due to 'value' being an array of empty or
 | 
	
		
			
				|  |  | +        // null-only elements), unknownFields may be empty. Discard the ArrayList if so.
 | 
	
		
			
				|  |  | +        return (unknownFields.size() == 0) ? null : unknownFields;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    @SuppressWarnings("unchecked")
 | 
	
		
			
				|  |  | -    private Class<T> getListType() {
 | 
	
		
			
				|  |  | -      return (Class<T>) ((ParameterizedType) type).getRawType();
 | 
	
		
			
				|  |  | +    protected UnknownFieldData writeData(Object value) {
 | 
	
		
			
				|  |  | +        // This implementation is for message/group extensions.
 | 
	
		
			
				|  |  | +        byte[] data;
 | 
	
		
			
				|  |  | +        try {
 | 
	
		
			
				|  |  | +            switch (type) {
 | 
	
		
			
				|  |  | +                case TYPE_GROUP:
 | 
	
		
			
				|  |  | +                    MessageNano groupValue = (MessageNano) value;
 | 
	
		
			
				|  |  | +                    int fieldNumber = WireFormatNano.getTagFieldNumber(tag);
 | 
	
		
			
				|  |  | +                    data = new byte[CodedOutputByteBufferNano.computeGroupSizeNoTag(groupValue)
 | 
	
		
			
				|  |  | +                            + CodedOutputByteBufferNano.computeTagSize(fieldNumber)];
 | 
	
		
			
				|  |  | +                    CodedOutputByteBufferNano out = CodedOutputByteBufferNano.newInstance(data);
 | 
	
		
			
				|  |  | +                    out.writeGroupNoTag(groupValue);
 | 
	
		
			
				|  |  | +                    // The endgroup tag must be included in the data payload.
 | 
	
		
			
				|  |  | +                    out.writeTag(fieldNumber, WireFormatNano.WIRETYPE_END_GROUP);
 | 
	
		
			
				|  |  | +                    break;
 | 
	
		
			
				|  |  | +                case TYPE_MESSAGE:
 | 
	
		
			
				|  |  | +                    MessageNano messageValue = (MessageNano) value;
 | 
	
		
			
				|  |  | +                    data = new byte[
 | 
	
		
			
				|  |  | +                            CodedOutputByteBufferNano.computeMessageSizeNoTag(messageValue)];
 | 
	
		
			
				|  |  | +                    CodedOutputByteBufferNano.newInstance(data).writeMessageNoTag(messageValue);
 | 
	
		
			
				|  |  | +                    break;
 | 
	
		
			
				|  |  | +                default:
 | 
	
		
			
				|  |  | +                    throw new IllegalArgumentException("Unknown type " + type);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        } catch (IOException e) {
 | 
	
		
			
				|  |  | +            // Should not happen
 | 
	
		
			
				|  |  | +            throw new IllegalStateException(e);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        return new UnknownFieldData(tag, data);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    protected void writeDataInto(T array, List<UnknownFieldData> unknownFields) {
 | 
	
		
			
				|  |  | +        // This implementation is for non-packed extensions.
 | 
	
		
			
				|  |  | +        int arrayLength = Array.getLength(array);
 | 
	
		
			
				|  |  | +        for (int i = 0; i < arrayLength; i++) {
 | 
	
		
			
				|  |  | +            Object element = Array.get(array, i);
 | 
	
		
			
				|  |  | +            if (element != null) {
 | 
	
		
			
				|  |  | +                unknownFields.add(writeData(element));
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      /**
 | 
	
		
			
				|  |  | -     * If the generic type is a list, returns the type of element in the list. Otherwise,
 | 
	
		
			
				|  |  | -     * returns the actual type.
 | 
	
		
			
				|  |  | +     * Represents an extension of a primitive (including enum) type. If there is no primitive
 | 
	
		
			
				|  |  | +     * extensions, this subclass will be removable by ProGuard.
 | 
	
		
			
				|  |  |       */
 | 
	
		
			
				|  |  | -    @SuppressWarnings("unchecked")
 | 
	
		
			
				|  |  | -    private Class<T> getTargetClass() {
 | 
	
		
			
				|  |  | -      if (isList()) {
 | 
	
		
			
				|  |  | -        return (Class<T>) ((ParameterizedType) type).getActualTypeArguments()[0];
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -      return (Class<T>) type;
 | 
	
		
			
				|  |  | +    private static class PrimitiveExtension<M extends ExtendableMessageNano<M>, T>
 | 
	
		
			
				|  |  | +            extends Extension<M, T> {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        /**
 | 
	
		
			
				|  |  | +         * Tag of a piece of non-packed data from the wire compatible with this extension.
 | 
	
		
			
				|  |  | +         */
 | 
	
		
			
				|  |  | +        private final int nonPackedTag;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        /**
 | 
	
		
			
				|  |  | +         * Tag of a piece of packed data from the wire compatible with this extension.
 | 
	
		
			
				|  |  | +         * 0 if the type of this extension is not packable.
 | 
	
		
			
				|  |  | +         */
 | 
	
		
			
				|  |  | +        private final int packedTag;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        public PrimitiveExtension(int type, Class<T> clazz, int tag, boolean repeated,
 | 
	
		
			
				|  |  | +                int nonPackedTag, int packedTag) {
 | 
	
		
			
				|  |  | +            super(type, clazz, tag, repeated);
 | 
	
		
			
				|  |  | +            this.nonPackedTag = nonPackedTag;
 | 
	
		
			
				|  |  | +            this.packedTag = packedTag;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        @Override
 | 
	
		
			
				|  |  | +        protected boolean isMatch(int unknownDataTag) {
 | 
	
		
			
				|  |  | +            if (repeated) {
 | 
	
		
			
				|  |  | +                return unknownDataTag == nonPackedTag || unknownDataTag == packedTag;
 | 
	
		
			
				|  |  | +            } else {
 | 
	
		
			
				|  |  | +                return unknownDataTag == tag;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        @Override
 | 
	
		
			
				|  |  | +        protected Object readData(CodedInputByteBufferNano input) {
 | 
	
		
			
				|  |  | +            try {
 | 
	
		
			
				|  |  | +                switch (type) {
 | 
	
		
			
				|  |  | +                    case TYPE_DOUBLE:
 | 
	
		
			
				|  |  | +                        return input.readDouble();
 | 
	
		
			
				|  |  | +                    case TYPE_FLOAT:
 | 
	
		
			
				|  |  | +                        return input.readFloat();
 | 
	
		
			
				|  |  | +                    case TYPE_INT64:
 | 
	
		
			
				|  |  | +                        return input.readInt64();
 | 
	
		
			
				|  |  | +                    case TYPE_UINT64:
 | 
	
		
			
				|  |  | +                        return input.readUInt64();
 | 
	
		
			
				|  |  | +                    case TYPE_INT32:
 | 
	
		
			
				|  |  | +                        return input.readInt32();
 | 
	
		
			
				|  |  | +                    case TYPE_FIXED64:
 | 
	
		
			
				|  |  | +                        return input.readFixed64();
 | 
	
		
			
				|  |  | +                    case TYPE_FIXED32:
 | 
	
		
			
				|  |  | +                        return input.readFixed32();
 | 
	
		
			
				|  |  | +                    case TYPE_BOOL:
 | 
	
		
			
				|  |  | +                        return input.readBool();
 | 
	
		
			
				|  |  | +                    case TYPE_STRING:
 | 
	
		
			
				|  |  | +                        return input.readString();
 | 
	
		
			
				|  |  | +                    case TYPE_BYTES:
 | 
	
		
			
				|  |  | +                        return input.readBytes();
 | 
	
		
			
				|  |  | +                    case TYPE_UINT32:
 | 
	
		
			
				|  |  | +                        return input.readUInt32();
 | 
	
		
			
				|  |  | +                    case TYPE_ENUM:
 | 
	
		
			
				|  |  | +                        return input.readEnum();
 | 
	
		
			
				|  |  | +                    case TYPE_SFIXED32:
 | 
	
		
			
				|  |  | +                        return input.readSFixed32();
 | 
	
		
			
				|  |  | +                    case TYPE_SFIXED64:
 | 
	
		
			
				|  |  | +                        return input.readSFixed64();
 | 
	
		
			
				|  |  | +                    case TYPE_SINT32:
 | 
	
		
			
				|  |  | +                        return input.readSInt32();
 | 
	
		
			
				|  |  | +                    case TYPE_SINT64:
 | 
	
		
			
				|  |  | +                        return input.readSInt64();
 | 
	
		
			
				|  |  | +                    default:
 | 
	
		
			
				|  |  | +                        throw new IllegalArgumentException("Unknown type " + type);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            } catch (IOException e) {
 | 
	
		
			
				|  |  | +                throw new IllegalArgumentException("Error reading extension field", e);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        @Override
 | 
	
		
			
				|  |  | +        protected void readDataInto(UnknownFieldData data, List<Object> resultList) {
 | 
	
		
			
				|  |  | +            // This implementation is for primitive typed extensions,
 | 
	
		
			
				|  |  | +            // which can read both packed and non-packed data.
 | 
	
		
			
				|  |  | +            if (data.tag == nonPackedTag) {
 | 
	
		
			
				|  |  | +                resultList.add(readData(CodedInputByteBufferNano.newInstance(data.bytes)));
 | 
	
		
			
				|  |  | +            } else {
 | 
	
		
			
				|  |  | +                CodedInputByteBufferNano buffer = CodedInputByteBufferNano.newInstance(data.bytes);
 | 
	
		
			
				|  |  | +                try {
 | 
	
		
			
				|  |  | +                    buffer.pushLimit(buffer.readRawVarint32()); // length limit
 | 
	
		
			
				|  |  | +                } catch (IOException e) {
 | 
	
		
			
				|  |  | +                    throw new IllegalArgumentException("Error reading extension field", e);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                while (!buffer.isAtEnd()) {
 | 
	
		
			
				|  |  | +                    resultList.add(readData(buffer));
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        @Override
 | 
	
		
			
				|  |  | +        protected final UnknownFieldData writeData(Object value) {
 | 
	
		
			
				|  |  | +            byte[] data;
 | 
	
		
			
				|  |  | +            try {
 | 
	
		
			
				|  |  | +                switch (type) {
 | 
	
		
			
				|  |  | +                    case TYPE_DOUBLE:
 | 
	
		
			
				|  |  | +                        Double doubleValue = (Double) value;
 | 
	
		
			
				|  |  | +                        data = new byte[
 | 
	
		
			
				|  |  | +                                CodedOutputByteBufferNano.computeDoubleSizeNoTag(doubleValue)];
 | 
	
		
			
				|  |  | +                        CodedOutputByteBufferNano.newInstance(data).writeDoubleNoTag(doubleValue);
 | 
	
		
			
				|  |  | +                        break;
 | 
	
		
			
				|  |  | +                    case TYPE_FLOAT:
 | 
	
		
			
				|  |  | +                        Float floatValue = (Float) value;
 | 
	
		
			
				|  |  | +                        data = new byte[
 | 
	
		
			
				|  |  | +                                CodedOutputByteBufferNano.computeFloatSizeNoTag(floatValue)];
 | 
	
		
			
				|  |  | +                        CodedOutputByteBufferNano.newInstance(data).writeFloatNoTag(floatValue);
 | 
	
		
			
				|  |  | +                        break;
 | 
	
		
			
				|  |  | +                    case TYPE_INT64:
 | 
	
		
			
				|  |  | +                        Long int64Value = (Long) value;
 | 
	
		
			
				|  |  | +                        data = new byte[
 | 
	
		
			
				|  |  | +                                CodedOutputByteBufferNano.computeInt64SizeNoTag(int64Value)];
 | 
	
		
			
				|  |  | +                        CodedOutputByteBufferNano.newInstance(data).writeInt64NoTag(int64Value);
 | 
	
		
			
				|  |  | +                        break;
 | 
	
		
			
				|  |  | +                    case TYPE_UINT64:
 | 
	
		
			
				|  |  | +                        Long uint64Value = (Long) value;
 | 
	
		
			
				|  |  | +                        data = new byte[
 | 
	
		
			
				|  |  | +                                CodedOutputByteBufferNano.computeUInt64SizeNoTag(uint64Value)];
 | 
	
		
			
				|  |  | +                        CodedOutputByteBufferNano.newInstance(data).writeUInt64NoTag(uint64Value);
 | 
	
		
			
				|  |  | +                        break;
 | 
	
		
			
				|  |  | +                    case TYPE_INT32:
 | 
	
		
			
				|  |  | +                        Integer int32Value = (Integer) value;
 | 
	
		
			
				|  |  | +                        data = new byte[
 | 
	
		
			
				|  |  | +                                CodedOutputByteBufferNano.computeInt32SizeNoTag(int32Value)];
 | 
	
		
			
				|  |  | +                        CodedOutputByteBufferNano.newInstance(data).writeInt32NoTag(int32Value);
 | 
	
		
			
				|  |  | +                        break;
 | 
	
		
			
				|  |  | +                    case TYPE_FIXED64:
 | 
	
		
			
				|  |  | +                        Long fixed64Value = (Long) value;
 | 
	
		
			
				|  |  | +                        data = new byte[
 | 
	
		
			
				|  |  | +                                CodedOutputByteBufferNano.computeFixed64SizeNoTag(fixed64Value)];
 | 
	
		
			
				|  |  | +                        CodedOutputByteBufferNano.newInstance(data).writeFixed64NoTag(fixed64Value);
 | 
	
		
			
				|  |  | +                        break;
 | 
	
		
			
				|  |  | +                    case TYPE_FIXED32:
 | 
	
		
			
				|  |  | +                        Integer fixed32Value = (Integer) value;
 | 
	
		
			
				|  |  | +                        data = new byte[
 | 
	
		
			
				|  |  | +                                CodedOutputByteBufferNano.computeFixed32SizeNoTag(fixed32Value)];
 | 
	
		
			
				|  |  | +                        CodedOutputByteBufferNano.newInstance(data).writeFixed32NoTag(fixed32Value);
 | 
	
		
			
				|  |  | +                        break;
 | 
	
		
			
				|  |  | +                    case TYPE_BOOL:
 | 
	
		
			
				|  |  | +                        Boolean boolValue = (Boolean) value;
 | 
	
		
			
				|  |  | +                        data = new byte[CodedOutputByteBufferNano.computeBoolSizeNoTag(boolValue)];
 | 
	
		
			
				|  |  | +                        CodedOutputByteBufferNano.newInstance(data).writeBoolNoTag(boolValue);
 | 
	
		
			
				|  |  | +                        break;
 | 
	
		
			
				|  |  | +                    case TYPE_STRING:
 | 
	
		
			
				|  |  | +                        String stringValue = (String) value;
 | 
	
		
			
				|  |  | +                        data = new byte[
 | 
	
		
			
				|  |  | +                                CodedOutputByteBufferNano.computeStringSizeNoTag(stringValue)];
 | 
	
		
			
				|  |  | +                        CodedOutputByteBufferNano.newInstance(data).writeStringNoTag(stringValue);
 | 
	
		
			
				|  |  | +                        break;
 | 
	
		
			
				|  |  | +                    case TYPE_BYTES:
 | 
	
		
			
				|  |  | +                        byte[] bytesValue = (byte[]) value;
 | 
	
		
			
				|  |  | +                        data = new byte[
 | 
	
		
			
				|  |  | +                                CodedOutputByteBufferNano.computeBytesSizeNoTag(bytesValue)];
 | 
	
		
			
				|  |  | +                        CodedOutputByteBufferNano.newInstance(data).writeBytesNoTag(bytesValue);
 | 
	
		
			
				|  |  | +                        break;
 | 
	
		
			
				|  |  | +                    case TYPE_UINT32:
 | 
	
		
			
				|  |  | +                        Integer uint32Value = (Integer) value;
 | 
	
		
			
				|  |  | +                        data = new byte[
 | 
	
		
			
				|  |  | +                                CodedOutputByteBufferNano.computeUInt32SizeNoTag(uint32Value)];
 | 
	
		
			
				|  |  | +                        CodedOutputByteBufferNano.newInstance(data).writeUInt32NoTag(uint32Value);
 | 
	
		
			
				|  |  | +                        break;
 | 
	
		
			
				|  |  | +                    case TYPE_ENUM:
 | 
	
		
			
				|  |  | +                        Integer enumValue = (Integer) value;
 | 
	
		
			
				|  |  | +                        data = new byte[CodedOutputByteBufferNano.computeEnumSizeNoTag(enumValue)];
 | 
	
		
			
				|  |  | +                        CodedOutputByteBufferNano.newInstance(data).writeEnumNoTag(enumValue);
 | 
	
		
			
				|  |  | +                        break;
 | 
	
		
			
				|  |  | +                    case TYPE_SFIXED32:
 | 
	
		
			
				|  |  | +                        Integer sfixed32Value = (Integer) value;
 | 
	
		
			
				|  |  | +                        data = new byte[
 | 
	
		
			
				|  |  | +                                CodedOutputByteBufferNano.computeSFixed32SizeNoTag(sfixed32Value)];
 | 
	
		
			
				|  |  | +                        CodedOutputByteBufferNano.newInstance(data)
 | 
	
		
			
				|  |  | +                                .writeSFixed32NoTag(sfixed32Value);
 | 
	
		
			
				|  |  | +                        break;
 | 
	
		
			
				|  |  | +                    case TYPE_SFIXED64:
 | 
	
		
			
				|  |  | +                        Long sfixed64Value = (Long) value;
 | 
	
		
			
				|  |  | +                        data = new byte[
 | 
	
		
			
				|  |  | +                                CodedOutputByteBufferNano.computeSFixed64SizeNoTag(sfixed64Value)];
 | 
	
		
			
				|  |  | +                        CodedOutputByteBufferNano.newInstance(data)
 | 
	
		
			
				|  |  | +                                .writeSFixed64NoTag(sfixed64Value);
 | 
	
		
			
				|  |  | +                        break;
 | 
	
		
			
				|  |  | +                    case TYPE_SINT32:
 | 
	
		
			
				|  |  | +                        Integer sint32Value = (Integer) value;
 | 
	
		
			
				|  |  | +                        data = new byte[
 | 
	
		
			
				|  |  | +                                CodedOutputByteBufferNano.computeSInt32SizeNoTag(sint32Value)];
 | 
	
		
			
				|  |  | +                        CodedOutputByteBufferNano.newInstance(data).writeSInt32NoTag(sint32Value);
 | 
	
		
			
				|  |  | +                        break;
 | 
	
		
			
				|  |  | +                    case TYPE_SINT64:
 | 
	
		
			
				|  |  | +                        Long sint64Value = (Long) value;
 | 
	
		
			
				|  |  | +                        data = new byte[
 | 
	
		
			
				|  |  | +                                CodedOutputByteBufferNano.computeSInt64SizeNoTag(sint64Value)];
 | 
	
		
			
				|  |  | +                        CodedOutputByteBufferNano.newInstance(data).writeSInt64NoTag(sint64Value);
 | 
	
		
			
				|  |  | +                        break;
 | 
	
		
			
				|  |  | +                    default:
 | 
	
		
			
				|  |  | +                        throw new IllegalArgumentException("Unknown type " + type);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            } catch (IOException e) {
 | 
	
		
			
				|  |  | +                // Should not happen
 | 
	
		
			
				|  |  | +                throw new IllegalStateException(e);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            return new UnknownFieldData(tag, data);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        @Override
 | 
	
		
			
				|  |  | +        protected void writeDataInto(T array, List<UnknownFieldData> unknownFields) {
 | 
	
		
			
				|  |  | +            if (tag == nonPackedTag) {
 | 
	
		
			
				|  |  | +                // Use base implementation for non-packed data
 | 
	
		
			
				|  |  | +                super.writeDataInto(array, unknownFields);
 | 
	
		
			
				|  |  | +            } else if (tag == packedTag) {
 | 
	
		
			
				|  |  | +                // Packed. Note that the array element type is guaranteed to be primitive, so there
 | 
	
		
			
				|  |  | +                // won't be any null elements, so no null check in this block. First get data size.
 | 
	
		
			
				|  |  | +                int arrayLength = Array.getLength(array);
 | 
	
		
			
				|  |  | +                int dataSize = 0;
 | 
	
		
			
				|  |  | +                switch (type) {
 | 
	
		
			
				|  |  | +                    case TYPE_BOOL:
 | 
	
		
			
				|  |  | +                        // Bools are stored as int32 but just as 0 or 1, so 1 byte each.
 | 
	
		
			
				|  |  | +                        dataSize = arrayLength;
 | 
	
		
			
				|  |  | +                        break;
 | 
	
		
			
				|  |  | +                    case TYPE_FIXED32:
 | 
	
		
			
				|  |  | +                    case TYPE_SFIXED32:
 | 
	
		
			
				|  |  | +                    case TYPE_FLOAT:
 | 
	
		
			
				|  |  | +                        dataSize = arrayLength * CodedOutputByteBufferNano.LITTLE_ENDIAN_32_SIZE;
 | 
	
		
			
				|  |  | +                        break;
 | 
	
		
			
				|  |  | +                    case TYPE_FIXED64:
 | 
	
		
			
				|  |  | +                    case TYPE_SFIXED64:
 | 
	
		
			
				|  |  | +                    case TYPE_DOUBLE:
 | 
	
		
			
				|  |  | +                        dataSize = arrayLength * CodedOutputByteBufferNano.LITTLE_ENDIAN_64_SIZE;
 | 
	
		
			
				|  |  | +                        break;
 | 
	
		
			
				|  |  | +                    case TYPE_INT32:
 | 
	
		
			
				|  |  | +                        for (int i = 0; i < arrayLength; i++) {
 | 
	
		
			
				|  |  | +                            dataSize += CodedOutputByteBufferNano.computeInt32SizeNoTag(
 | 
	
		
			
				|  |  | +                                    Array.getInt(array, i));
 | 
	
		
			
				|  |  | +                        }
 | 
	
		
			
				|  |  | +                        break;
 | 
	
		
			
				|  |  | +                    case TYPE_SINT32:
 | 
	
		
			
				|  |  | +                        for (int i = 0; i < arrayLength; i++) {
 | 
	
		
			
				|  |  | +                            dataSize += CodedOutputByteBufferNano.computeSInt32SizeNoTag(
 | 
	
		
			
				|  |  | +                                    Array.getInt(array, i));
 | 
	
		
			
				|  |  | +                        }
 | 
	
		
			
				|  |  | +                        break;
 | 
	
		
			
				|  |  | +                    case TYPE_UINT32:
 | 
	
		
			
				|  |  | +                        for (int i = 0; i < arrayLength; i++) {
 | 
	
		
			
				|  |  | +                            dataSize += CodedOutputByteBufferNano.computeUInt32SizeNoTag(
 | 
	
		
			
				|  |  | +                                    Array.getInt(array, i));
 | 
	
		
			
				|  |  | +                        }
 | 
	
		
			
				|  |  | +                        break;
 | 
	
		
			
				|  |  | +                    case TYPE_INT64:
 | 
	
		
			
				|  |  | +                        for (int i = 0; i < arrayLength; i++) {
 | 
	
		
			
				|  |  | +                            dataSize += CodedOutputByteBufferNano.computeInt64SizeNoTag(
 | 
	
		
			
				|  |  | +                                    Array.getLong(array, i));
 | 
	
		
			
				|  |  | +                        }
 | 
	
		
			
				|  |  | +                        break;
 | 
	
		
			
				|  |  | +                    case TYPE_SINT64:
 | 
	
		
			
				|  |  | +                        for (int i = 0; i < arrayLength; i++) {
 | 
	
		
			
				|  |  | +                            dataSize += CodedOutputByteBufferNano.computeSInt64SizeNoTag(
 | 
	
		
			
				|  |  | +                                    Array.getLong(array, i));
 | 
	
		
			
				|  |  | +                        }
 | 
	
		
			
				|  |  | +                        break;
 | 
	
		
			
				|  |  | +                    case TYPE_UINT64:
 | 
	
		
			
				|  |  | +                        for (int i = 0; i < arrayLength; i++) {
 | 
	
		
			
				|  |  | +                            dataSize += CodedOutputByteBufferNano.computeUInt64SizeNoTag(
 | 
	
		
			
				|  |  | +                                    Array.getLong(array, i));
 | 
	
		
			
				|  |  | +                        }
 | 
	
		
			
				|  |  | +                        break;
 | 
	
		
			
				|  |  | +                    case TYPE_ENUM:
 | 
	
		
			
				|  |  | +                        for (int i = 0; i < arrayLength; i++) {
 | 
	
		
			
				|  |  | +                            dataSize += CodedOutputByteBufferNano.computeEnumSizeNoTag(
 | 
	
		
			
				|  |  | +                                    Array.getInt(array, i));
 | 
	
		
			
				|  |  | +                        }
 | 
	
		
			
				|  |  | +                        break;
 | 
	
		
			
				|  |  | +                    default:
 | 
	
		
			
				|  |  | +                        throw new IllegalArgumentException("Unexpected non-packable type " + type);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                // Then construct payload.
 | 
	
		
			
				|  |  | +                int payloadSize =
 | 
	
		
			
				|  |  | +                        dataSize + CodedOutputByteBufferNano.computeRawVarint32Size(dataSize);
 | 
	
		
			
				|  |  | +                byte[] data = new byte[payloadSize];
 | 
	
		
			
				|  |  | +                CodedOutputByteBufferNano output = CodedOutputByteBufferNano.newInstance(data);
 | 
	
		
			
				|  |  | +                try {
 | 
	
		
			
				|  |  | +                    output.writeRawVarint32(dataSize);
 | 
	
		
			
				|  |  | +                    switch (type) {
 | 
	
		
			
				|  |  | +                        case TYPE_BOOL:
 | 
	
		
			
				|  |  | +                            for (int i = 0; i < arrayLength; i++) {
 | 
	
		
			
				|  |  | +                                output.writeBoolNoTag(Array.getBoolean(array, i));
 | 
	
		
			
				|  |  | +                            }
 | 
	
		
			
				|  |  | +                            break;
 | 
	
		
			
				|  |  | +                        case TYPE_FIXED32:
 | 
	
		
			
				|  |  | +                            for (int i = 0; i < arrayLength; i++) {
 | 
	
		
			
				|  |  | +                                output.writeFixed32NoTag(Array.getInt(array, i));
 | 
	
		
			
				|  |  | +                            }
 | 
	
		
			
				|  |  | +                            break;
 | 
	
		
			
				|  |  | +                        case TYPE_SFIXED32:
 | 
	
		
			
				|  |  | +                            for (int i = 0; i < arrayLength; i++) {
 | 
	
		
			
				|  |  | +                                output.writeSFixed32NoTag(Array.getInt(array, i));
 | 
	
		
			
				|  |  | +                            }
 | 
	
		
			
				|  |  | +                            break;
 | 
	
		
			
				|  |  | +                        case TYPE_FLOAT:
 | 
	
		
			
				|  |  | +                            for (int i = 0; i < arrayLength; i++) {
 | 
	
		
			
				|  |  | +                                output.writeFloatNoTag(Array.getFloat(array, i));
 | 
	
		
			
				|  |  | +                            }
 | 
	
		
			
				|  |  | +                            break;
 | 
	
		
			
				|  |  | +                        case TYPE_FIXED64:
 | 
	
		
			
				|  |  | +                            for (int i = 0; i < arrayLength; i++) {
 | 
	
		
			
				|  |  | +                                output.writeFixed64NoTag(Array.getLong(array, i));
 | 
	
		
			
				|  |  | +                            }
 | 
	
		
			
				|  |  | +                            break;
 | 
	
		
			
				|  |  | +                        case TYPE_SFIXED64:
 | 
	
		
			
				|  |  | +                            for (int i = 0; i < arrayLength; i++) {
 | 
	
		
			
				|  |  | +                                output.writeSFixed64NoTag(Array.getLong(array, i));
 | 
	
		
			
				|  |  | +                            }
 | 
	
		
			
				|  |  | +                            break;
 | 
	
		
			
				|  |  | +                        case TYPE_DOUBLE:
 | 
	
		
			
				|  |  | +                            for (int i = 0; i < arrayLength; i++) {
 | 
	
		
			
				|  |  | +                                output.writeDoubleNoTag(Array.getDouble(array, i));
 | 
	
		
			
				|  |  | +                            }
 | 
	
		
			
				|  |  | +                            break;
 | 
	
		
			
				|  |  | +                        case TYPE_INT32:
 | 
	
		
			
				|  |  | +                            for (int i = 0; i < arrayLength; i++) {
 | 
	
		
			
				|  |  | +                                output.writeInt32NoTag(Array.getInt(array, i));
 | 
	
		
			
				|  |  | +                            }
 | 
	
		
			
				|  |  | +                            break;
 | 
	
		
			
				|  |  | +                        case TYPE_SINT32:
 | 
	
		
			
				|  |  | +                            for (int i = 0; i < arrayLength; i++) {
 | 
	
		
			
				|  |  | +                                output.writeSInt32NoTag(Array.getInt(array, i));
 | 
	
		
			
				|  |  | +                            }
 | 
	
		
			
				|  |  | +                            break;
 | 
	
		
			
				|  |  | +                        case TYPE_UINT32:
 | 
	
		
			
				|  |  | +                            for (int i = 0; i < arrayLength; i++) {
 | 
	
		
			
				|  |  | +                                output.writeUInt32NoTag(Array.getInt(array, i));
 | 
	
		
			
				|  |  | +                            }
 | 
	
		
			
				|  |  | +                            break;
 | 
	
		
			
				|  |  | +                        case TYPE_INT64:
 | 
	
		
			
				|  |  | +                            for (int i = 0; i < arrayLength; i++) {
 | 
	
		
			
				|  |  | +                                output.writeInt64NoTag(Array.getLong(array, i));
 | 
	
		
			
				|  |  | +                            }
 | 
	
		
			
				|  |  | +                            break;
 | 
	
		
			
				|  |  | +                        case TYPE_SINT64:
 | 
	
		
			
				|  |  | +                            for (int i = 0; i < arrayLength; i++) {
 | 
	
		
			
				|  |  | +                                output.writeSInt64NoTag(Array.getLong(array, i));
 | 
	
		
			
				|  |  | +                            }
 | 
	
		
			
				|  |  | +                            break;
 | 
	
		
			
				|  |  | +                        case TYPE_UINT64:
 | 
	
		
			
				|  |  | +                            for (int i = 0; i < arrayLength; i++) {
 | 
	
		
			
				|  |  | +                                output.writeUInt64NoTag(Array.getLong(array, i));
 | 
	
		
			
				|  |  | +                            }
 | 
	
		
			
				|  |  | +                            break;
 | 
	
		
			
				|  |  | +                        case TYPE_ENUM:
 | 
	
		
			
				|  |  | +                            for (int i = 0; i < arrayLength; i++) {
 | 
	
		
			
				|  |  | +                                output.writeEnumNoTag(Array.getInt(array, i));
 | 
	
		
			
				|  |  | +                            }
 | 
	
		
			
				|  |  | +                            break;
 | 
	
		
			
				|  |  | +                        default:
 | 
	
		
			
				|  |  | +                            throw new IllegalArgumentException("Unpackable type " + type);
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                } catch (IOException e) {
 | 
	
		
			
				|  |  | +                    // Should not happen.
 | 
	
		
			
				|  |  | +                    throw new IllegalStateException(e);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                unknownFields.add(new UnknownFieldData(tag, data));
 | 
	
		
			
				|  |  | +            } else {
 | 
	
		
			
				|  |  | +                throw new IllegalArgumentException("Unexpected repeated extension tag " + tag
 | 
	
		
			
				|  |  | +                        + ", unequal to both non-packed variant " + nonPackedTag
 | 
	
		
			
				|  |  | +                        + " and packed variant " + packedTag);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  |  }
 |