• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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