• 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 com.google.protobuf.Descriptors.EnumValueDescriptor;
34 import com.google.protobuf.Descriptors.FieldDescriptor;
35 import java.io.IOException;
36 import java.lang.reflect.Field;
37 import java.nio.ByteBuffer;
38 import java.util.ArrayList;
39 import java.util.List;
40 import java.util.Map;
41 
42 @SuppressWarnings("unchecked")
43 final class ExtensionSchemaFull extends ExtensionSchema<FieldDescriptor> {
44 
45   private static final long EXTENSION_FIELD_OFFSET = getExtensionsFieldOffset();
46 
getExtensionsFieldOffset()47   private static <T> long getExtensionsFieldOffset() {
48     try {
49       Field field = GeneratedMessageV3.ExtendableMessage.class.getDeclaredField("extensions");
50       return UnsafeUtil.objectFieldOffset(field);
51     } catch (Throwable e) {
52       throw new IllegalStateException("Unable to lookup extension field offset");
53     }
54   }
55 
56   @Override
hasExtensions(MessageLite prototype)57   boolean hasExtensions(MessageLite prototype) {
58     return prototype instanceof GeneratedMessageV3.ExtendableMessage;
59   }
60 
61   @Override
getExtensions(Object message)62   public FieldSet<FieldDescriptor> getExtensions(Object message) {
63     return (FieldSet<FieldDescriptor>) UnsafeUtil.getObject(message, EXTENSION_FIELD_OFFSET);
64   }
65 
66   @Override
setExtensions(Object message, FieldSet<FieldDescriptor> extensions)67   void setExtensions(Object message, FieldSet<FieldDescriptor> extensions) {
68     UnsafeUtil.putObject(message, EXTENSION_FIELD_OFFSET, extensions);
69   }
70 
71   @Override
getMutableExtensions(Object message)72   FieldSet<FieldDescriptor> getMutableExtensions(Object message) {
73     FieldSet<FieldDescriptor> extensions = getExtensions(message);
74     if (extensions.isImmutable()) {
75       extensions = extensions.clone();
76       setExtensions(message, extensions);
77     }
78     return extensions;
79   }
80 
81   @Override
makeImmutable(Object message)82   void makeImmutable(Object message) {
83     getExtensions(message).makeImmutable();
84   }
85 
86   @Override
parseExtension( Reader reader, Object extensionObject, ExtensionRegistryLite extensionRegistry, FieldSet<FieldDescriptor> extensions, UB unknownFields, UnknownFieldSchema<UT, UB> unknownFieldSchema)87   <UT, UB> UB parseExtension(
88       Reader reader,
89       Object extensionObject,
90       ExtensionRegistryLite extensionRegistry,
91       FieldSet<FieldDescriptor> extensions,
92       UB unknownFields,
93       UnknownFieldSchema<UT, UB> unknownFieldSchema)
94       throws IOException {
95     ExtensionRegistry.ExtensionInfo extension = (ExtensionRegistry.ExtensionInfo) extensionObject;
96     int fieldNumber = extension.descriptor.getNumber();
97 
98     if (extension.descriptor.isRepeated() && extension.descriptor.isPacked()) {
99       Object value = null;
100       switch (extension.descriptor.getLiteType()) {
101         case DOUBLE:
102           {
103             List<Double> list = new ArrayList<Double>();
104             reader.readDoubleList(list);
105             value = list;
106             break;
107           }
108         case FLOAT:
109           {
110             List<Float> list = new ArrayList<Float>();
111             reader.readFloatList(list);
112             value = list;
113             break;
114           }
115         case INT64:
116           {
117             List<Long> list = new ArrayList<Long>();
118             reader.readInt64List(list);
119             value = list;
120             break;
121           }
122         case UINT64:
123           {
124             List<Long> list = new ArrayList<Long>();
125             reader.readUInt64List(list);
126             value = list;
127             break;
128           }
129         case INT32:
130           {
131             List<Integer> list = new ArrayList<Integer>();
132             reader.readInt32List(list);
133             value = list;
134             break;
135           }
136         case FIXED64:
137           {
138             List<Long> list = new ArrayList<Long>();
139             reader.readFixed64List(list);
140             value = list;
141             break;
142           }
143         case FIXED32:
144           {
145             List<Integer> list = new ArrayList<Integer>();
146             reader.readFixed32List(list);
147             value = list;
148             break;
149           }
150         case BOOL:
151           {
152             List<Boolean> list = new ArrayList<Boolean>();
153             reader.readBoolList(list);
154             value = list;
155             break;
156           }
157         case UINT32:
158           {
159             List<Integer> list = new ArrayList<Integer>();
160             reader.readUInt32List(list);
161             value = list;
162             break;
163           }
164         case SFIXED32:
165           {
166             List<Integer> list = new ArrayList<Integer>();
167             reader.readSFixed32List(list);
168             value = list;
169             break;
170           }
171         case SFIXED64:
172           {
173             List<Long> list = new ArrayList<Long>();
174             reader.readSFixed64List(list);
175             value = list;
176             break;
177           }
178         case SINT32:
179           {
180             List<Integer> list = new ArrayList<Integer>();
181             reader.readSInt32List(list);
182             value = list;
183             break;
184           }
185         case SINT64:
186           {
187             List<Long> list = new ArrayList<Long>();
188             reader.readSInt64List(list);
189             value = list;
190             break;
191           }
192         case ENUM:
193           {
194             List<Integer> list = new ArrayList<Integer>();
195             reader.readEnumList(list);
196             List<EnumValueDescriptor> enumList = new ArrayList<EnumValueDescriptor>();
197             for (int number : list) {
198               EnumValueDescriptor enumDescriptor =
199                   extension.descriptor.getEnumType().findValueByNumber(number);
200               if (enumDescriptor != null) {
201                 enumList.add(enumDescriptor);
202               } else {
203                 unknownFields =
204                     SchemaUtil.storeUnknownEnum(
205                         fieldNumber, number, unknownFields, unknownFieldSchema);
206               }
207             }
208             value = enumList;
209             break;
210           }
211         default:
212           throw new IllegalStateException(
213               "Type cannot be packed: " + extension.descriptor.getLiteType());
214       }
215       extensions.setField(extension.descriptor, value);
216     } else {
217       Object value = null;
218       // Enum is a special case because unknown enum values will be put into UnknownFieldSetLite.
219       if (extension.descriptor.getLiteType() == WireFormat.FieldType.ENUM) {
220         int number = reader.readInt32();
221         Object enumValue = extension.descriptor.getEnumType().findValueByNumber(number);
222         if (enumValue == null) {
223           return SchemaUtil.storeUnknownEnum(
224               fieldNumber, number, unknownFields, unknownFieldSchema);
225         }
226         value = enumValue;
227       } else {
228         switch (extension.descriptor.getLiteType()) {
229           case DOUBLE:
230             value = reader.readDouble();
231             break;
232           case FLOAT:
233             value = reader.readFloat();
234             break;
235           case INT64:
236             value = reader.readInt64();
237             break;
238           case UINT64:
239             value = reader.readUInt64();
240             break;
241           case INT32:
242             value = reader.readInt32();
243             break;
244           case FIXED64:
245             value = reader.readFixed64();
246             break;
247           case FIXED32:
248             value = reader.readFixed32();
249             break;
250           case BOOL:
251             value = reader.readBool();
252             break;
253           case BYTES:
254             value = reader.readBytes();
255             break;
256           case UINT32:
257             value = reader.readUInt32();
258             break;
259           case SFIXED32:
260             value = reader.readSFixed32();
261             break;
262           case SFIXED64:
263             value = reader.readSFixed64();
264             break;
265           case SINT32:
266             value = reader.readSInt32();
267             break;
268           case SINT64:
269             value = reader.readSInt64();
270             break;
271 
272           case STRING:
273             value = reader.readString();
274             break;
275           case GROUP:
276             value = reader.readGroup(extension.defaultInstance.getClass(), extensionRegistry);
277             break;
278 
279           case MESSAGE:
280             value = reader.readMessage(extension.defaultInstance.getClass(), extensionRegistry);
281             break;
282 
283           case ENUM:
284             throw new IllegalStateException("Shouldn't reach here.");
285         }
286       }
287       if (extension.descriptor.isRepeated()) {
288         extensions.addRepeatedField(extension.descriptor, value);
289       } else {
290         switch (extension.descriptor.getLiteType()) {
291           case MESSAGE:
292           case GROUP:
293             Object oldValue = extensions.getField(extension.descriptor);
294             if (oldValue != null) {
295               value = Internal.mergeMessage(oldValue, value);
296             }
297             break;
298           default:
299             break;
300         }
301         extensions.setField(extension.descriptor, value);
302       }
303     }
304     return unknownFields;
305   }
306 
307   @Override
extensionNumber(Map.Entry<?, ?> extension)308   int extensionNumber(Map.Entry<?, ?> extension) {
309     FieldDescriptor descriptor = (FieldDescriptor) extension.getKey();
310     return descriptor.getNumber();
311   }
312 
313   @Override
serializeExtension(Writer writer, Map.Entry<?, ?> extension)314   void serializeExtension(Writer writer, Map.Entry<?, ?> extension) throws IOException {
315     FieldDescriptor descriptor = (FieldDescriptor) extension.getKey();
316     if (descriptor.isRepeated()) {
317       switch (descriptor.getLiteType()) {
318         case DOUBLE:
319           SchemaUtil.writeDoubleList(
320               descriptor.getNumber(),
321               (List<Double>) extension.getValue(),
322               writer,
323               descriptor.isPacked());
324           break;
325         case FLOAT:
326           SchemaUtil.writeFloatList(
327               descriptor.getNumber(),
328               (List<Float>) extension.getValue(),
329               writer,
330               descriptor.isPacked());
331           break;
332         case INT64:
333           SchemaUtil.writeInt64List(
334               descriptor.getNumber(),
335               (List<Long>) extension.getValue(),
336               writer,
337               descriptor.isPacked());
338           break;
339         case UINT64:
340           SchemaUtil.writeUInt64List(
341               descriptor.getNumber(),
342               (List<Long>) extension.getValue(),
343               writer,
344               descriptor.isPacked());
345           break;
346         case INT32:
347           SchemaUtil.writeInt32List(
348               descriptor.getNumber(),
349               (List<Integer>) extension.getValue(),
350               writer,
351               descriptor.isPacked());
352           break;
353         case FIXED64:
354           SchemaUtil.writeFixed64List(
355               descriptor.getNumber(),
356               (List<Long>) extension.getValue(),
357               writer,
358               descriptor.isPacked());
359           break;
360         case FIXED32:
361           SchemaUtil.writeFixed32List(
362               descriptor.getNumber(),
363               (List<Integer>) extension.getValue(),
364               writer,
365               descriptor.isPacked());
366           break;
367         case BOOL:
368           SchemaUtil.writeBoolList(
369               descriptor.getNumber(),
370               (List<Boolean>) extension.getValue(),
371               writer,
372               descriptor.isPacked());
373           break;
374         case BYTES:
375           SchemaUtil.writeBytesList(
376               descriptor.getNumber(), (List<ByteString>) extension.getValue(), writer);
377           break;
378         case UINT32:
379           SchemaUtil.writeUInt32List(
380               descriptor.getNumber(),
381               (List<Integer>) extension.getValue(),
382               writer,
383               descriptor.isPacked());
384           break;
385         case SFIXED32:
386           SchemaUtil.writeSFixed32List(
387               descriptor.getNumber(),
388               (List<Integer>) extension.getValue(),
389               writer,
390               descriptor.isPacked());
391           break;
392         case SFIXED64:
393           SchemaUtil.writeSFixed64List(
394               descriptor.getNumber(),
395               (List<Long>) extension.getValue(),
396               writer,
397               descriptor.isPacked());
398           break;
399         case SINT32:
400           SchemaUtil.writeSInt32List(
401               descriptor.getNumber(),
402               (List<Integer>) extension.getValue(),
403               writer,
404               descriptor.isPacked());
405           break;
406         case SINT64:
407           SchemaUtil.writeSInt64List(
408               descriptor.getNumber(),
409               (List<Long>) extension.getValue(),
410               writer,
411               descriptor.isPacked());
412           break;
413         case ENUM:
414           {
415             List<EnumValueDescriptor> enumList = (List<EnumValueDescriptor>) extension.getValue();
416             List<Integer> list = new ArrayList<Integer>();
417             for (EnumValueDescriptor d : enumList) {
418               list.add(d.getNumber());
419             }
420             SchemaUtil.writeInt32List(descriptor.getNumber(), list, writer, descriptor.isPacked());
421             break;
422           }
423         case STRING:
424           SchemaUtil.writeStringList(
425               descriptor.getNumber(), (List<String>) extension.getValue(), writer);
426           break;
427         case GROUP:
428           SchemaUtil.writeGroupList(descriptor.getNumber(), (List<?>) extension.getValue(), writer);
429           break;
430         case MESSAGE:
431           SchemaUtil.writeMessageList(
432               descriptor.getNumber(), (List<?>) extension.getValue(), writer);
433           break;
434       }
435     } else {
436       switch (descriptor.getLiteType()) {
437         case DOUBLE:
438           writer.writeDouble(descriptor.getNumber(), (Double) extension.getValue());
439           break;
440         case FLOAT:
441           writer.writeFloat(descriptor.getNumber(), (Float) extension.getValue());
442           break;
443         case INT64:
444           writer.writeInt64(descriptor.getNumber(), (Long) extension.getValue());
445           break;
446         case UINT64:
447           writer.writeUInt64(descriptor.getNumber(), (Long) extension.getValue());
448           break;
449         case INT32:
450           writer.writeInt32(descriptor.getNumber(), (Integer) extension.getValue());
451           break;
452         case FIXED64:
453           writer.writeFixed64(descriptor.getNumber(), (Long) extension.getValue());
454           break;
455         case FIXED32:
456           writer.writeFixed32(descriptor.getNumber(), (Integer) extension.getValue());
457           break;
458         case BOOL:
459           writer.writeBool(descriptor.getNumber(), (Boolean) extension.getValue());
460           break;
461         case BYTES:
462           writer.writeBytes(descriptor.getNumber(), (ByteString) extension.getValue());
463           break;
464         case UINT32:
465           writer.writeUInt32(descriptor.getNumber(), (Integer) extension.getValue());
466           break;
467         case SFIXED32:
468           writer.writeSFixed32(descriptor.getNumber(), (Integer) extension.getValue());
469           break;
470         case SFIXED64:
471           writer.writeSFixed64(descriptor.getNumber(), (Long) extension.getValue());
472           break;
473         case SINT32:
474           writer.writeSInt32(descriptor.getNumber(), (Integer) extension.getValue());
475           break;
476         case SINT64:
477           writer.writeSInt64(descriptor.getNumber(), (Long) extension.getValue());
478           break;
479         case ENUM:
480           writer.writeInt32(
481               descriptor.getNumber(), ((EnumValueDescriptor) extension.getValue()).getNumber());
482           break;
483         case STRING:
484           writer.writeString(descriptor.getNumber(), (String) extension.getValue());
485           break;
486         case GROUP:
487           writer.writeGroup(descriptor.getNumber(), extension.getValue());
488           break;
489         case MESSAGE:
490           writer.writeMessage(descriptor.getNumber(), extension.getValue());
491           break;
492       }
493     }
494   }
495 
496   @Override
findExtensionByNumber( ExtensionRegistryLite extensionRegistry, MessageLite defaultInstance, int number)497   Object findExtensionByNumber(
498       ExtensionRegistryLite extensionRegistry, MessageLite defaultInstance, int number) {
499     return ((ExtensionRegistry) extensionRegistry)
500         .findExtensionByNumber(((Message) defaultInstance).getDescriptorForType(), number);
501   }
502 
503   @Override
parseLengthPrefixedMessageSetItem( Reader reader, Object extension, ExtensionRegistryLite extensionRegistry, FieldSet<FieldDescriptor> extensions)504   void parseLengthPrefixedMessageSetItem(
505       Reader reader,
506       Object extension,
507       ExtensionRegistryLite extensionRegistry,
508       FieldSet<FieldDescriptor> extensions)
509       throws IOException {
510     ExtensionRegistry.ExtensionInfo extensionInfo = (ExtensionRegistry.ExtensionInfo) extension;
511 
512     if (ExtensionRegistryLite.isEagerlyParseMessageSets()) {
513       Object value =
514           reader.readMessage(extensionInfo.defaultInstance.getClass(), extensionRegistry);
515       extensions.setField(extensionInfo.descriptor, value);
516     } else {
517       extensions.setField(
518           extensionInfo.descriptor,
519           new LazyField(extensionInfo.defaultInstance, extensionRegistry, reader.readBytes()));
520     }
521   }
522 
523   @Override
parseMessageSetItem( ByteString data, Object extension, ExtensionRegistryLite extensionRegistry, FieldSet<FieldDescriptor> extensions)524   void parseMessageSetItem(
525       ByteString data,
526       Object extension,
527       ExtensionRegistryLite extensionRegistry,
528       FieldSet<FieldDescriptor> extensions)
529       throws IOException {
530     ExtensionRegistry.ExtensionInfo extensionInfo = (ExtensionRegistry.ExtensionInfo) extension;
531     Object value = extensionInfo.defaultInstance.newBuilderForType().buildPartial();
532 
533     if (ExtensionRegistryLite.isEagerlyParseMessageSets()) {
534       Reader reader = BinaryReader.newInstance(ByteBuffer.wrap(data.toByteArray()), true);
535       Protobuf.getInstance().mergeFrom(value, reader, extensionRegistry);
536       extensions.setField(extensionInfo.descriptor, value);
537 
538       if (reader.getFieldNumber() != Reader.READ_DONE) {
539         throw InvalidProtocolBufferException.invalidEndTag();
540       }
541     } else {
542       extensions.setField(
543           extensionInfo.descriptor,
544           new LazyField(extensionInfo.defaultInstance, extensionRegistry, data));
545     }
546   }
547 }
548