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