1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // https://developers.google.com/protocol-buffers/ 4 // 5 // Redistribution and use in source and binary forms, with or without 6 // modification, are permitted provided that the following conditions are 7 // met: 8 // 9 // * Redistributions of source code must retain the above copyright 10 // notice, this list of conditions and the following disclaimer. 11 // * Redistributions in binary form must reproduce the above 12 // copyright notice, this list of conditions and the following disclaimer 13 // in the documentation and/or other materials provided with the 14 // distribution. 15 // * Neither the name of Google Inc. nor the names of its 16 // contributors may be used to endorse or promote products derived from 17 // this software without specific prior written permission. 18 // 19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31 package com.google.protobuf; 32 33 /** 34 * RawMessageInfo stores the same amount of information as {@link MessageInfo} but in a more compact 35 * format. 36 */ 37 final class RawMessageInfo implements MessageInfo { 38 39 private final MessageLite defaultInstance; 40 41 /** 42 * The compact format packs everything in a String object and a Object[] array. The String object 43 * is encoded with field number, field type, hasbits offset, oneof index, etc., whereas the 44 * Object[] array contains field references, class references, instance references, etc. 45 * 46 * <p>The String object encodes a sequence of integers into UTF-16 characters. For each int, it 47 * will be encoding into 1 to 3 UTF-16 characters depending on its unsigned value: 48 * 49 * <ul> 50 * <li>1 char: [c1: 0x0000 - 0xD7FF] = int of the same value. 51 * <li>2 chars: [c1: 0xE000 - 0xFFFF], [c2: 0x0000 - 0xD7FF] = (c2 << 13) | (c1 & 0x1FFF) 52 * <li>3 chars: [c1: 0xE000 - 0xFFFF], [c2: 0xE000 - 0xFFFF], [c3: 0x0000 - 0xD7FF] = (c3 << 26) 53 * | ((c2 & 0x1FFF) << 13) | (c1 & 0x1FFF) 54 * </ul> 55 * 56 * <p>Note that we don't use UTF-16 surrogate pairs [0xD800 - 0xDFFF] because they have to come in 57 * pairs to form a valid UTF-16char sequence and don't help us encode values more efficiently. 58 * 59 * <p>The integer sequence encoded in the String object has the following layout: 60 * 61 * <ul> 62 * <li>[0]: flags, flags & 0x1 = is proto2?, flags & 0x2 = is message?. 63 * <li>[1]: field count, if 0, this is the end of the integer sequence and the corresponding 64 * Object[] array should be null. 65 * <li>[2]: oneof count 66 * <li>[3]: hasbits count, how many hasbits integers are generated. 67 * <li>[4]: min field number 68 * <li>[5]: max field number 69 * <li>[6]: total number of entries need to allocate 70 * <li>[7]: map field count 71 * <li>[8]: repeated field count, this doesn't include map fields. 72 * <li>[9]: size of checkInitialized array 73 * <li>[...]: field entries 74 * </ul> 75 * 76 * <p>Each field entry starts with a field number and the field type: 77 * 78 * <ul> 79 * <li>[0]: field number 80 * <li>[1]: field type with extra bits: 81 * <ul> 82 * <li>v & 0xFF = field type as defined in the FieldType class 83 * <li>v & 0x100 = is required? 84 * <li>v & 0x200 = is checkUtf8? 85 * <li>v & 0x400 = needs isInitialized check? 86 * <li>v & 0x800 = is map field with proto2 enum value? 87 * </ul> 88 * </ul> 89 * 90 * If the file is proto2 and this is a singular field: 91 * 92 * <ul> 93 * <li>[2]: hasbits offset 94 * </ul> 95 * 96 * If the field is in an oneof: 97 * 98 * <ul> 99 * <li>[2]: oenof index 100 * </ul> 101 * 102 * For other types, the field entry only has field number and field type. 103 * 104 * <p>The Object[] array has 3 sections: 105 * 106 * <ul> 107 * <li>---- oneof section ---- 108 * <ul> 109 * <li>[0]: value field for oneof 1. 110 * <li>[1]: case field for oneof 1. 111 * <li>... 112 * <li>[.]: value field for oneof n. 113 * <li>[.]: case field for oneof n. 114 * </ul> 115 * <li>---- hasbits section ---- 116 * <ul> 117 * <li>[.]: hasbits field 1 118 * <li>[.]: hasbits field 2 119 * <li>... 120 * <li>[.]: hasbits field n 121 * </ul> 122 * <li>---- field section ---- 123 * <ul> 124 * <li>[...]: field entries 125 * </ul> 126 * </ul> 127 * 128 * <p>In the Object[] array, field entries are ordered in the same way as field entries in the 129 * String object. The size of each entry is determined by the field type. 130 * 131 * <ul> 132 * <li>Oneof field: 133 * <ul> 134 * <li>Oneof message field: 135 * <ul> 136 * <li>[0]: message class reference. 137 * </ul> 138 * <li>Oneof enum fieldin proto2: 139 * <ul> 140 * <li>[0]: EnumLiteMap 141 * </ul> 142 * <li>For all other oneof fields, field entry in the Object[] array is empty. 143 * </ul> 144 * <li>Repeated message field: 145 * <ul> 146 * <li>[0]: field reference 147 * <li>[1]: message class reference 148 * </ul> 149 * <li>Proto2 singular/repeated enum field: 150 * <ul> 151 * <li>[0]: field reference 152 * <li>[1]: EnumLiteMap 153 * </ul> 154 * <li>Map field with a proto2 enum value: 155 * <ul> 156 * <li>[0]: field reference 157 * <li>[1]: map default entry instance 158 * <li>[2]: EnumLiteMap 159 * </ul> 160 * <li>Map field with other value types: 161 * <ul> 162 * <li>[0]: field reference 163 * <li>[1]: map default entry instance 164 * </ul> 165 * <li>All other field type: 166 * <ul> 167 * <li>[0]: field reference 168 * </ul> 169 * </ul> 170 * 171 * <p>In order to read the field info from this compact format, a reader needs to progress through 172 * the String object and the Object[] array simultaneously. 173 */ 174 private final String info; 175 176 private final Object[] objects; 177 private final int flags; 178 RawMessageInfo(MessageLite defaultInstance, String info, Object[] objects)179 RawMessageInfo(MessageLite defaultInstance, String info, Object[] objects) { 180 this.defaultInstance = defaultInstance; 181 this.info = info; 182 this.objects = objects; 183 int position = 0; 184 int value = (int) info.charAt(position++); 185 if (value < 0xD800) { 186 flags = value; 187 } else { 188 int result = value & 0x1FFF; 189 int shift = 13; 190 while ((value = info.charAt(position++)) >= 0xD800) { 191 result |= (value & 0x1FFF) << shift; 192 shift += 13; 193 } 194 flags = result | (value << shift); 195 } 196 } 197 getStringInfo()198 String getStringInfo() { 199 return info; 200 } 201 getObjects()202 Object[] getObjects() { 203 return objects; 204 } 205 206 @Override getDefaultInstance()207 public MessageLite getDefaultInstance() { 208 return defaultInstance; 209 } 210 211 @Override getSyntax()212 public ProtoSyntax getSyntax() { 213 return (flags & 0x1) == 0x1 ? ProtoSyntax.PROTO2 : ProtoSyntax.PROTO3; 214 } 215 216 @Override isMessageSetWireFormat()217 public boolean isMessageSetWireFormat() { 218 return (flags & 0x2) == 0x2; 219 } 220 } 221