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