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 import java.io.IOException; 34 35 /** 36 * This class is used internally by the Protocol Buffer library and generated message 37 * implementations. It is public only because those generated messages do not reside in the {@code 38 * protobuf} package. Others should not use this class directly. 39 * 40 * <p>This class contains constants and helper functions useful for dealing with the Protocol Buffer 41 * wire format. 42 * 43 * @author kenton@google.com Kenton Varda 44 */ 45 public final class WireFormat { 46 // Do not allow instantiation. WireFormat()47 private WireFormat() {} 48 49 static final int FIXED32_SIZE = 4; 50 static final int FIXED64_SIZE = 8; 51 static final int MAX_VARINT32_SIZE = 5; 52 static final int MAX_VARINT64_SIZE = 10; 53 static final int MAX_VARINT_SIZE = 10; 54 55 public static final int WIRETYPE_VARINT = 0; 56 public static final int WIRETYPE_FIXED64 = 1; 57 public static final int WIRETYPE_LENGTH_DELIMITED = 2; 58 public static final int WIRETYPE_START_GROUP = 3; 59 public static final int WIRETYPE_END_GROUP = 4; 60 public static final int WIRETYPE_FIXED32 = 5; 61 62 static final int TAG_TYPE_BITS = 3; 63 static final int TAG_TYPE_MASK = (1 << TAG_TYPE_BITS) - 1; 64 65 /** Given a tag value, determines the wire type (the lower 3 bits). */ getTagWireType(final int tag)66 public static int getTagWireType(final int tag) { 67 return tag & TAG_TYPE_MASK; 68 } 69 70 /** Given a tag value, determines the field number (the upper 29 bits). */ getTagFieldNumber(final int tag)71 public static int getTagFieldNumber(final int tag) { 72 return tag >>> TAG_TYPE_BITS; 73 } 74 75 /** Makes a tag value given a field number and wire type. */ makeTag(final int fieldNumber, final int wireType)76 static int makeTag(final int fieldNumber, final int wireType) { 77 return (fieldNumber << TAG_TYPE_BITS) | wireType; 78 } 79 80 /** 81 * Lite equivalent to {@link Descriptors.FieldDescriptor.JavaType}. This is only here to support 82 * the lite runtime and should not be used by users. 83 */ 84 public enum JavaType { 85 INT(0), 86 LONG(0L), 87 FLOAT(0F), 88 DOUBLE(0D), 89 BOOLEAN(false), 90 STRING(""), 91 BYTE_STRING(ByteString.EMPTY), 92 ENUM(null), 93 MESSAGE(null); 94 JavaType(final Object defaultDefault)95 JavaType(final Object defaultDefault) { 96 this.defaultDefault = defaultDefault; 97 } 98 99 /** The default default value for fields of this type, if it's a primitive type. */ getDefaultDefault()100 Object getDefaultDefault() { 101 return defaultDefault; 102 } 103 104 private final Object defaultDefault; 105 } 106 107 /** 108 * Lite equivalent to {@link Descriptors.FieldDescriptor.Type}. This is only here to support the 109 * lite runtime and should not be used by users. 110 */ 111 public enum FieldType { 112 DOUBLE(JavaType.DOUBLE, WIRETYPE_FIXED64), 113 FLOAT(JavaType.FLOAT, WIRETYPE_FIXED32), 114 INT64(JavaType.LONG, WIRETYPE_VARINT), 115 UINT64(JavaType.LONG, WIRETYPE_VARINT), 116 INT32(JavaType.INT, WIRETYPE_VARINT), 117 FIXED64(JavaType.LONG, WIRETYPE_FIXED64), 118 FIXED32(JavaType.INT, WIRETYPE_FIXED32), 119 BOOL(JavaType.BOOLEAN, WIRETYPE_VARINT), STRING(JavaType.STRING, WIRETYPE_LENGTH_DELIMITED)120 STRING(JavaType.STRING, WIRETYPE_LENGTH_DELIMITED) { 121 @Override 122 public boolean isPackable() { 123 return false; 124 } 125 }, GROUP(JavaType.MESSAGE, WIRETYPE_START_GROUP)126 GROUP(JavaType.MESSAGE, WIRETYPE_START_GROUP) { 127 @Override 128 public boolean isPackable() { 129 return false; 130 } 131 }, MESSAGE(JavaType.MESSAGE, WIRETYPE_LENGTH_DELIMITED)132 MESSAGE(JavaType.MESSAGE, WIRETYPE_LENGTH_DELIMITED) { 133 @Override 134 public boolean isPackable() { 135 return false; 136 } 137 }, BYTES(JavaType.BYTE_STRING, WIRETYPE_LENGTH_DELIMITED)138 BYTES(JavaType.BYTE_STRING, WIRETYPE_LENGTH_DELIMITED) { 139 @Override 140 public boolean isPackable() { 141 return false; 142 } 143 }, 144 UINT32(JavaType.INT, WIRETYPE_VARINT), 145 ENUM(JavaType.ENUM, WIRETYPE_VARINT), 146 SFIXED32(JavaType.INT, WIRETYPE_FIXED32), 147 SFIXED64(JavaType.LONG, WIRETYPE_FIXED64), 148 SINT32(JavaType.INT, WIRETYPE_VARINT), 149 SINT64(JavaType.LONG, WIRETYPE_VARINT); 150 FieldType(final JavaType javaType, final int wireType)151 FieldType(final JavaType javaType, final int wireType) { 152 this.javaType = javaType; 153 this.wireType = wireType; 154 } 155 156 private final JavaType javaType; 157 private final int wireType; 158 getJavaType()159 public JavaType getJavaType() { 160 return javaType; 161 } 162 getWireType()163 public int getWireType() { 164 return wireType; 165 } 166 isPackable()167 public boolean isPackable() { 168 return true; 169 } 170 } 171 172 // Field numbers for fields in MessageSet wire format. 173 static final int MESSAGE_SET_ITEM = 1; 174 static final int MESSAGE_SET_TYPE_ID = 2; 175 static final int MESSAGE_SET_MESSAGE = 3; 176 177 // Tag numbers. 178 static final int MESSAGE_SET_ITEM_TAG = makeTag(MESSAGE_SET_ITEM, WIRETYPE_START_GROUP); 179 static final int MESSAGE_SET_ITEM_END_TAG = makeTag(MESSAGE_SET_ITEM, WIRETYPE_END_GROUP); 180 static final int MESSAGE_SET_TYPE_ID_TAG = makeTag(MESSAGE_SET_TYPE_ID, WIRETYPE_VARINT); 181 static final int MESSAGE_SET_MESSAGE_TAG = 182 makeTag(MESSAGE_SET_MESSAGE, WIRETYPE_LENGTH_DELIMITED); 183 184 /** 185 * Validation level for handling incoming string field data which potentially contain non-UTF8 186 * bytes. 187 */ 188 enum Utf8Validation { 189 /** Eagerly parses to String; silently accepts invalid UTF8 bytes. */ 190 LOOSE { 191 @Override readString(CodedInputStream input)192 Object readString(CodedInputStream input) throws IOException { 193 return input.readString(); 194 } 195 }, 196 /** Eagerly parses to String; throws an IOException on invalid bytes. */ 197 STRICT { 198 @Override readString(CodedInputStream input)199 Object readString(CodedInputStream input) throws IOException { 200 return input.readStringRequireUtf8(); 201 } 202 }, 203 /** Keep data as ByteString; validation/conversion to String is lazy. */ 204 LAZY { 205 @Override readString(CodedInputStream input)206 Object readString(CodedInputStream input) throws IOException { 207 return input.readBytes(); 208 } 209 }; 210 211 /** Read a string field from the input with the proper UTF8 validation. */ readString(CodedInputStream input)212 abstract Object readString(CodedInputStream input) throws IOException; 213 } 214 215 /** 216 * Read a field of any primitive type for immutable messages from a CodedInputStream. Enums, 217 * groups, and embedded messages are not handled by this method. 218 * 219 * @param input The stream from which to read. 220 * @param type Declared type of the field. 221 * @param utf8Validation Different string UTF8 validation level for handling string fields. 222 * @return An object representing the field's value, of the exact type which would be returned by 223 * {@link Message#getField(Descriptors.FieldDescriptor)} for this field. 224 */ readPrimitiveField( CodedInputStream input, FieldType type, Utf8Validation utf8Validation)225 static Object readPrimitiveField( 226 CodedInputStream input, FieldType type, Utf8Validation utf8Validation) throws IOException { 227 switch (type) { 228 case DOUBLE: 229 return input.readDouble(); 230 case FLOAT: 231 return input.readFloat(); 232 case INT64: 233 return input.readInt64(); 234 case UINT64: 235 return input.readUInt64(); 236 case INT32: 237 return input.readInt32(); 238 case FIXED64: 239 return input.readFixed64(); 240 case FIXED32: 241 return input.readFixed32(); 242 case BOOL: 243 return input.readBool(); 244 case BYTES: 245 return input.readBytes(); 246 case UINT32: 247 return input.readUInt32(); 248 case SFIXED32: 249 return input.readSFixed32(); 250 case SFIXED64: 251 return input.readSFixed64(); 252 case SINT32: 253 return input.readSInt32(); 254 case SINT64: 255 return input.readSInt64(); 256 257 case STRING: 258 return utf8Validation.readString(input); 259 case GROUP: 260 throw new IllegalArgumentException("readPrimitiveField() cannot handle nested groups."); 261 case MESSAGE: 262 throw new IllegalArgumentException("readPrimitiveField() cannot handle embedded messages."); 263 case ENUM: 264 // We don't handle enums because we don't know what to do if the 265 // value is not recognized. 266 throw new IllegalArgumentException("readPrimitiveField() cannot handle enums."); 267 } 268 269 throw new RuntimeException("There is no way to get here, but the compiler thinks otherwise."); 270 } 271 } 272