1b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// Protocol Buffers - Google's data interchange format 2b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// Copyright 2008 Google Inc. All rights reserved. 3b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// https://developers.google.com/protocol-buffers/ 4b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// 5b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// Redistribution and use in source and binary forms, with or without 6b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// modification, are permitted provided that the following conditions are 7b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// met: 8b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// 9b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// * Redistributions of source code must retain the above copyright 10b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// notice, this list of conditions and the following disclaimer. 11b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// * Redistributions in binary form must reproduce the above 12b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// copyright notice, this list of conditions and the following disclaimer 13b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// in the documentation and/or other materials provided with the 14b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// distribution. 15b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// * Neither the name of Google Inc. nor the names of its 16b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// contributors may be used to endorse or promote products derived from 17b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// this software without specific prior written permission. 18b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// 19b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 31b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerpackage com.google.protobuf.nano; 32b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 33b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerimport com.google.protobuf.nano.MapFactories.MapFactory; 34b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 35b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerimport java.io.IOException; 36b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerimport java.nio.charset.Charset; 37b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerimport java.util.Arrays; 38b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerimport java.util.Map; 39b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerimport java.util.Map.Entry; 40b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 41b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/** 42b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * The classes contained within are used internally by the Protocol Buffer 43b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * library and generated message implementations. They are public only because 44b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * those generated messages do not reside in the {@code protobuf} package. 45b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Others should not use this class directly. 46b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * 47b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * @author kenton@google.com (Kenton Varda) 48b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 49b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerpublic final class InternalNano { 50b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 51b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static final int TYPE_DOUBLE = 1; 52b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static final int TYPE_FLOAT = 2; 53b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static final int TYPE_INT64 = 3; 54b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static final int TYPE_UINT64 = 4; 55b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static final int TYPE_INT32 = 5; 56b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static final int TYPE_FIXED64 = 6; 57b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static final int TYPE_FIXED32 = 7; 58b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static final int TYPE_BOOL = 8; 59b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static final int TYPE_STRING = 9; 60b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static final int TYPE_GROUP = 10; 61b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static final int TYPE_MESSAGE = 11; 62b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static final int TYPE_BYTES = 12; 63b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static final int TYPE_UINT32 = 13; 64b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static final int TYPE_ENUM = 14; 65b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static final int TYPE_SFIXED32 = 15; 66b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static final int TYPE_SFIXED64 = 16; 67b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static final int TYPE_SINT32 = 17; 68b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static final int TYPE_SINT64 = 18; 69b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 70b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer protected static final Charset UTF_8 = Charset.forName("UTF-8"); 71b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer protected static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1"); 72b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 73b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private InternalNano() {} 74b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 75b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 76b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * An object to provide synchronization when lazily initializing static fields 77b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * of {@link MessageNano} subclasses. 78b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * <p> 79b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * To enable earlier versions of ProGuard to inline short methods from a 80b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * generated MessageNano subclass to the call sites, that class must not have 81b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * a class initializer, which will be created if there is any static variable 82b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * initializers. To lazily initialize the static variables in a thread-safe 83b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * manner, the initialization code will synchronize on this object. 84b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 85b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static final Object LAZY_INIT_LOCK = new Object(); 86b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 87b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 88b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Helper called by generated code to construct default values for string 89b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * fields. 90b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * <p> 91b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * The protocol compiler does not actually contain a UTF-8 decoder -- it 92b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * just pushes UTF-8-encoded text around without touching it. The one place 93b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * where this presents a problem is when generating Java string literals. 94b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Unicode characters in the string literal would normally need to be encoded 95b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * using a Unicode escape sequence, which would require decoding them. 96b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * To get around this, protoc instead embeds the UTF-8 bytes into the 97b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * generated code and leaves it to the runtime library to decode them. 98b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * <p> 99b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * It gets worse, though. If protoc just generated a byte array, like: 100b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * new byte[] {0x12, 0x34, 0x56, 0x78} 101b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Java actually generates *code* which allocates an array and then fills 102b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * in each value. This is much less efficient than just embedding the bytes 103b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * directly into the bytecode. To get around this, we need another 104b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * work-around. String literals are embedded directly, so protoc actually 105b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * generates a string literal corresponding to the bytes. The easiest way 106b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * to do this is to use the ISO-8859-1 character set, which corresponds to 107b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * the first 256 characters of the Unicode range. Protoc can then use 108b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * good old CEscape to generate the string. 109b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * <p> 110b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * So we have a string literal which represents a set of bytes which 111b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * represents another string. This function -- stringDefaultValue -- 112b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * converts from the generated string to the string we actually want. The 113b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * generated code calls this automatically. 114b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 115b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static String stringDefaultValue(String bytes) { 116b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return new String(bytes.getBytes(ISO_8859_1), InternalNano.UTF_8); 117b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 118b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 119b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 120b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Helper called by generated code to construct default values for bytes 121b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * fields. 122b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * <p> 123b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * This is a lot like {@link #stringDefaultValue}, but for bytes fields. 124b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * In this case we only need the second of the two hacks -- allowing us to 125b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * embed raw bytes as a string literal with ISO-8859-1 encoding. 126b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 127b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static byte[] bytesDefaultValue(String bytes) { 128b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return bytes.getBytes(ISO_8859_1); 129b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 130b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 131b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 132b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Helper function to convert a string into UTF-8 while turning the 133b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * UnsupportedEncodingException to a RuntimeException. 134b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 135b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static byte[] copyFromUtf8(final String text) { 136b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return text.getBytes(InternalNano.UTF_8); 137b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 138b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 139b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 140b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Checks repeated int field equality; null-value and 0-length fields are 141b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * considered equal. 142b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 143b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static boolean equals(int[] field1, int[] field2) { 144b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (field1 == null || field1.length == 0) { 145b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return field2 == null || field2.length == 0; 146b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 147b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return Arrays.equals(field1, field2); 148b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 149b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 150b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 151b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 152b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Checks repeated long field equality; null-value and 0-length fields are 153b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * considered equal. 154b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 155b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static boolean equals(long[] field1, long[] field2) { 156b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (field1 == null || field1.length == 0) { 157b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return field2 == null || field2.length == 0; 158b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 159b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return Arrays.equals(field1, field2); 160b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 161b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 162b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 163b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 164b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Checks repeated float field equality; null-value and 0-length fields are 165b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * considered equal. 166b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 167b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static boolean equals(float[] field1, float[] field2) { 168b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (field1 == null || field1.length == 0) { 169b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return field2 == null || field2.length == 0; 170b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 171b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return Arrays.equals(field1, field2); 172b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 173b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 174b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 175b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 176b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Checks repeated double field equality; null-value and 0-length fields are 177b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * considered equal. 178b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 179b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static boolean equals(double[] field1, double[] field2) { 180b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (field1 == null || field1.length == 0) { 181b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return field2 == null || field2.length == 0; 182b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 183b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return Arrays.equals(field1, field2); 184b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 185b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 186b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 187b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 188b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Checks repeated boolean field equality; null-value and 0-length fields are 189b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * considered equal. 190b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 191b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static boolean equals(boolean[] field1, boolean[] field2) { 192b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (field1 == null || field1.length == 0) { 193b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return field2 == null || field2.length == 0; 194b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 195b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return Arrays.equals(field1, field2); 196b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 197b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 198b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 199b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 200b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Checks repeated bytes field equality. Only non-null elements are tested. 201b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Returns true if the two fields have the same sequence of non-null 202b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * elements. Null-value fields and fields of any length with only null 203b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * elements are considered equal. 204b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 205b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static boolean equals(byte[][] field1, byte[][] field2) { 206b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int index1 = 0; 207b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int length1 = field1 == null ? 0 : field1.length; 208b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int index2 = 0; 209b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int length2 = field2 == null ? 0 : field2.length; 210b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer while (true) { 211b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer while (index1 < length1 && field1[index1] == null) { 212b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer index1++; 213b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 214b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer while (index2 < length2 && field2[index2] == null) { 215b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer index2++; 216b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 217b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer boolean atEndOf1 = index1 >= length1; 218b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer boolean atEndOf2 = index2 >= length2; 219b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (atEndOf1 && atEndOf2) { 220b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // no more non-null elements to test in both arrays 221b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return true; 222b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else if (atEndOf1 != atEndOf2) { 223b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // one of the arrays have extra non-null elements 224b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return false; 225b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else if (!Arrays.equals(field1[index1], field2[index2])) { 226b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // element mismatch 227b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return false; 228b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 229b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer index1++; 230b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer index2++; 231b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 232b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 233b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 234b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 235b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Checks repeated string/message field equality. Only non-null elements are 236b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * tested. Returns true if the two fields have the same sequence of non-null 237b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * elements. Null-value fields and fields of any length with only null 238b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * elements are considered equal. 239b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 240b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static boolean equals(Object[] field1, Object[] field2) { 241b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int index1 = 0; 242b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int length1 = field1 == null ? 0 : field1.length; 243b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int index2 = 0; 244b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int length2 = field2 == null ? 0 : field2.length; 245b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer while (true) { 246b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer while (index1 < length1 && field1[index1] == null) { 247b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer index1++; 248b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 249b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer while (index2 < length2 && field2[index2] == null) { 250b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer index2++; 251b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 252b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer boolean atEndOf1 = index1 >= length1; 253b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer boolean atEndOf2 = index2 >= length2; 254b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (atEndOf1 && atEndOf2) { 255b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // no more non-null elements to test in both arrays 256b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return true; 257b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else if (atEndOf1 != atEndOf2) { 258b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // one of the arrays have extra non-null elements 259b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return false; 260b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else if (!field1[index1].equals(field2[index2])) { 261b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // element mismatch 262b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return false; 263b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 264b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer index1++; 265b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer index2++; 266b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 267b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 268b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 269b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 270b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Computes the hash code of a repeated int field. Null-value and 0-length 271b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * fields have the same hash code. 272b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 273b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int hashCode(int[] field) { 274b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return field == null || field.length == 0 ? 0 : Arrays.hashCode(field); 275b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 276b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 277b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 278b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Computes the hash code of a repeated long field. Null-value and 0-length 279b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * fields have the same hash code. 280b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 281b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int hashCode(long[] field) { 282b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return field == null || field.length == 0 ? 0 : Arrays.hashCode(field); 283b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 284b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 285b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 286b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Computes the hash code of a repeated float field. Null-value and 0-length 287b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * fields have the same hash code. 288b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 289b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int hashCode(float[] field) { 290b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return field == null || field.length == 0 ? 0 : Arrays.hashCode(field); 291b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 292b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 293b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 294b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Computes the hash code of a repeated double field. Null-value and 0-length 295b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * fields have the same hash code. 296b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 297b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int hashCode(double[] field) { 298b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return field == null || field.length == 0 ? 0 : Arrays.hashCode(field); 299b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 300b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 301b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 302b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Computes the hash code of a repeated boolean field. Null-value and 0-length 303b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * fields have the same hash code. 304b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 305b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int hashCode(boolean[] field) { 306b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return field == null || field.length == 0 ? 0 : Arrays.hashCode(field); 307b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 308b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 309b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 310b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Computes the hash code of a repeated bytes field. Only the sequence of all 311b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * non-null elements are used in the computation. Null-value fields and fields 312b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * of any length with only null elements have the same hash code. 313b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 314b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int hashCode(byte[][] field) { 315b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int result = 0; 316b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer for (int i = 0, size = field == null ? 0 : field.length; i < size; i++) { 317b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer byte[] element = field[i]; 318b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (element != null) { 319b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer result = 31 * result + Arrays.hashCode(element); 320b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 321b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 322b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return result; 323b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 324b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 325b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 326b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Computes the hash code of a repeated string/message field. Only the 327b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * sequence of all non-null elements are used in the computation. Null-value 328b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * fields and fields of any length with only null elements have the same hash 329b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * code. 330b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 331b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static int hashCode(Object[] field) { 332b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int result = 0; 333b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer for (int i = 0, size = field == null ? 0 : field.length; i < size; i++) { 334b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Object element = field[i]; 335b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (element != null) { 336b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer result = 31 * result + element.hashCode(); 337b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 338b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 339b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return result; 340b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 341b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private static Object primitiveDefaultValue(int type) { 342b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer switch (type) { 343b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case TYPE_BOOL: 344b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return Boolean.FALSE; 345b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case TYPE_BYTES: 346b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return WireFormatNano.EMPTY_BYTES; 347b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case TYPE_STRING: 348b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return ""; 349b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case TYPE_FLOAT: 350b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return Float.valueOf(0); 351b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case TYPE_DOUBLE: 352b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return Double.valueOf(0); 353b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case TYPE_ENUM: 354b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case TYPE_FIXED32: 355b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case TYPE_INT32: 356b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case TYPE_UINT32: 357b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case TYPE_SINT32: 358b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case TYPE_SFIXED32: 359b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return Integer.valueOf(0); 360b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case TYPE_INT64: 361b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case TYPE_UINT64: 362b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case TYPE_SINT64: 363b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case TYPE_FIXED64: 364b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case TYPE_SFIXED64: 365b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return Long.valueOf(0L); 366b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case TYPE_MESSAGE: 367b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer case TYPE_GROUP: 368b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer default: 369b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw new IllegalArgumentException( 370b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "Type: " + type + " is not a primitive type."); 371b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 372b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 373b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 374b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 375b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Merges the map entry into the map field. Note this is only supposed to 376b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * be called by generated messages. 377b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * 378b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * @param map the map field; may be null, in which case a map will be 379b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * instantiated using the {@link MapFactories.MapFactory} 380b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * @param input the input byte buffer 381b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * @param keyType key type, as defined in InternalNano.TYPE_* 382b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * @param valueType value type, as defined in InternalNano.TYPE_* 383b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * @param value an new instance of the value, if the value is a TYPE_MESSAGE; 384b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * otherwise this parameter can be null and will be ignored. 385b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * @param keyTag wire tag for the key 386b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * @param valueTag wire tag for the value 387b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * @return the map field 388b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * @throws IOException 389b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 390b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer @SuppressWarnings("unchecked") 391b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static final <K, V> Map<K, V> mergeMapEntry( 392b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer CodedInputByteBufferNano input, 393b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Map<K, V> map, 394b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer MapFactory mapFactory, 395b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int keyType, 396b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int valueType, 397b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer V value, 398b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int keyTag, 399b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int valueTag) throws IOException { 400b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer map = mapFactory.forMap(map); 401b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final int length = input.readRawVarint32(); 402b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer final int oldLimit = input.pushLimit(length); 403b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer K key = null; 404b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer while (true) { 405b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int tag = input.readTag(); 406b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (tag == 0) { 407b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer break; 408b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 409b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (tag == keyTag) { 410b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer key = (K) input.readPrimitiveField(keyType); 411b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else if (tag == valueTag) { 412b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (valueType == TYPE_MESSAGE) { 413b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer input.readMessage((MessageNano) value); 414b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 415b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer value = (V) input.readPrimitiveField(valueType); 416b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 417b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } else { 418b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (!input.skipField(tag)) { 419b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer break; 420b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 421b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 422b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 423b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer input.checkLastTagWas(0); 424b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer input.popLimit(oldLimit); 425b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 426b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (key == null) { 427b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // key can only be primitive types. 428b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer key = (K) primitiveDefaultValue(keyType); 429b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 430b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 431b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (value == null) { 432b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // message type value will be initialized by code-gen. 433b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer value = (V) primitiveDefaultValue(valueType); 434b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 435b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 436b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer map.put(key, value); 437b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return map; 438b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 439b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 440b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static <K, V> void serializeMapField( 441b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer CodedOutputByteBufferNano output, 442b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Map<K, V> map, int number, int keyType, int valueType) 443b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throws IOException { 444b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer for (Entry<K, V> entry: map.entrySet()) { 445b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer K key = entry.getKey(); 446b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer V value = entry.getValue(); 447b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (key == null || value == null) { 448b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw new IllegalStateException( 449b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "keys and values in maps cannot be null"); 450b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 451b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int entrySize = 452b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer CodedOutputByteBufferNano.computeFieldSize(1, keyType, key) + 453b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer CodedOutputByteBufferNano.computeFieldSize(2, valueType, value); 454b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer output.writeTag(number, WireFormatNano.WIRETYPE_LENGTH_DELIMITED); 455b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer output.writeRawVarint32(entrySize); 456b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer output.writeField(1, keyType, key); 457b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer output.writeField(2, valueType, value); 458b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 459b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 460b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 461b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static <K, V> int computeMapFieldSize( 462b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Map<K, V> map, int number, int keyType, int valueType) { 463b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int size = 0; 464b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int tagSize = CodedOutputByteBufferNano.computeTagSize(number); 465b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer for (Entry<K, V> entry: map.entrySet()) { 466b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer K key = entry.getKey(); 467b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer V value = entry.getValue(); 468b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (key == null || value == null) { 469b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw new IllegalStateException( 470b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "keys and values in maps cannot be null"); 471b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 472b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int entrySize = 473b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer CodedOutputByteBufferNano.computeFieldSize(1, keyType, key) + 474b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer CodedOutputByteBufferNano.computeFieldSize(2, valueType, value); 475b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer size += tagSize + entrySize 476b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer + CodedOutputByteBufferNano.computeRawVarint32Size(entrySize); 477b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 478b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return size; 479b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 480b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 481b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /** 482b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Checks whether two {@link Map} are equal. We don't use the default equals 483b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * method of {@link Map} because it compares by identity not by content for 484b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * byte arrays. 485b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */ 486b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static <K, V> boolean equals(Map<K, V> a, Map<K, V> b) { 487b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (a == b) { 488b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return true; 489b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 490b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (a == null) { 491b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return b.size() == 0; 492b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 493b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (b == null) { 494b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return a.size() == 0; 495b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 496b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (a.size() != b.size()) { 497b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return false; 498b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 499b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer for (Entry<K, V> entry : a.entrySet()) { 500b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (!b.containsKey(entry.getKey())) { 501b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return false; 502b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 503b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (!equalsMapValue(entry.getValue(), b.get(entry.getKey()))) { 504b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return false; 505b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 506b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 507b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return true; 508b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 509b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 510b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private static boolean equalsMapValue(Object a, Object b) { 511b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (a == null || b == null) { 512b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw new IllegalStateException( 513b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer "keys and values in maps cannot be null"); 514b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 515b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (a instanceof byte[] && b instanceof byte[]) { 516b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return Arrays.equals((byte[]) a, (byte[]) b); 517b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 518b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return a.equals(b); 519b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 520b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 521b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static <K, V> int hashCode(Map<K, V> map) { 522b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (map == null) { 523b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return 0; 524b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 525b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int result = 0; 526b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer for (Entry<K, V> entry : map.entrySet()) { 527b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer result += hashCodeForMap(entry.getKey()) 528b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer ^ hashCodeForMap(entry.getValue()); 529b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 530b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return result; 531b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 532b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 533b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private static int hashCodeForMap(Object o) { 534b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (o instanceof byte[]) { 535b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return Arrays.hashCode((byte[]) o); 536b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 537b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return o.hashCode(); 538b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 539b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 540b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // This avoids having to make FieldArray public. 541b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static void cloneUnknownFieldData(ExtendableMessageNano original, 542b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer ExtendableMessageNano cloned) { 543b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (original.unknownFieldData != null) { 544b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer cloned.unknownFieldData = (FieldArray) original.unknownFieldData.clone(); 545b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 546b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 547b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} 548