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