• 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 /**
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