1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file or at 6 // https://developers.google.com/open-source/licenses/bsd 7 8 package com.google.protobuf; 9 10 import com.google.protobuf.GeneratedMessageLite.ExtensionDescriptor; 11 import java.io.IOException; 12 import java.util.ArrayList; 13 import java.util.List; 14 import java.util.Map; 15 16 @CheckReturnValue 17 @SuppressWarnings("unchecked") 18 final class ExtensionSchemaLite extends ExtensionSchema<ExtensionDescriptor> { 19 20 @Override hasExtensions(MessageLite prototype)21 boolean hasExtensions(MessageLite prototype) { 22 return prototype instanceof GeneratedMessageLite.ExtendableMessage; 23 } 24 25 @Override getExtensions(Object message)26 FieldSet<ExtensionDescriptor> getExtensions(Object message) { 27 return ((GeneratedMessageLite.ExtendableMessage<?, ?>) message).extensions; 28 } 29 30 @Override setExtensions(Object message, FieldSet<ExtensionDescriptor> extensions)31 void setExtensions(Object message, FieldSet<ExtensionDescriptor> extensions) { 32 ((GeneratedMessageLite.ExtendableMessage<?, ?>) message).extensions = extensions; 33 } 34 35 @Override getMutableExtensions(Object message)36 FieldSet<ExtensionDescriptor> getMutableExtensions(Object message) { 37 return ((GeneratedMessageLite.ExtendableMessage<?, ?>) message).ensureExtensionsAreMutable(); 38 } 39 40 @Override makeImmutable(Object message)41 void makeImmutable(Object message) { 42 getExtensions(message).makeImmutable(); 43 } 44 45 @Override parseExtension( Object containerMessage, Reader reader, Object extensionObject, ExtensionRegistryLite extensionRegistry, FieldSet<ExtensionDescriptor> extensions, UB unknownFields, UnknownFieldSchema<UT, UB> unknownFieldSchema)46 <UT, UB> UB parseExtension( 47 Object containerMessage, 48 Reader reader, 49 Object extensionObject, 50 ExtensionRegistryLite extensionRegistry, 51 FieldSet<ExtensionDescriptor> extensions, 52 UB unknownFields, 53 UnknownFieldSchema<UT, UB> unknownFieldSchema) 54 throws IOException { 55 GeneratedMessageLite.GeneratedExtension<?, ?> extension = 56 (GeneratedMessageLite.GeneratedExtension<?, ?>) extensionObject; 57 int fieldNumber = extension.getNumber(); 58 59 if (extension.descriptor.isRepeated() && extension.descriptor.isPacked()) { 60 Object value = null; 61 switch (extension.getLiteType()) { 62 case DOUBLE: 63 { 64 List<Double> list = new ArrayList<Double>(); 65 reader.readDoubleList(list); 66 value = list; 67 break; 68 } 69 case FLOAT: 70 { 71 List<Float> list = new ArrayList<Float>(); 72 reader.readFloatList(list); 73 value = list; 74 break; 75 } 76 case INT64: 77 { 78 List<Long> list = new ArrayList<Long>(); 79 reader.readInt64List(list); 80 value = list; 81 break; 82 } 83 case UINT64: 84 { 85 List<Long> list = new ArrayList<Long>(); 86 reader.readUInt64List(list); 87 value = list; 88 break; 89 } 90 case INT32: 91 { 92 List<Integer> list = new ArrayList<Integer>(); 93 reader.readInt32List(list); 94 value = list; 95 break; 96 } 97 case FIXED64: 98 { 99 List<Long> list = new ArrayList<Long>(); 100 reader.readFixed64List(list); 101 value = list; 102 break; 103 } 104 case FIXED32: 105 { 106 List<Integer> list = new ArrayList<Integer>(); 107 reader.readFixed32List(list); 108 value = list; 109 break; 110 } 111 case BOOL: 112 { 113 List<Boolean> list = new ArrayList<Boolean>(); 114 reader.readBoolList(list); 115 value = list; 116 break; 117 } 118 case UINT32: 119 { 120 List<Integer> list = new ArrayList<Integer>(); 121 reader.readUInt32List(list); 122 value = list; 123 break; 124 } 125 case SFIXED32: 126 { 127 List<Integer> list = new ArrayList<Integer>(); 128 reader.readSFixed32List(list); 129 value = list; 130 break; 131 } 132 case SFIXED64: 133 { 134 List<Long> list = new ArrayList<Long>(); 135 reader.readSFixed64List(list); 136 value = list; 137 break; 138 } 139 case SINT32: 140 { 141 List<Integer> list = new ArrayList<Integer>(); 142 reader.readSInt32List(list); 143 value = list; 144 break; 145 } 146 case SINT64: 147 { 148 List<Long> list = new ArrayList<Long>(); 149 reader.readSInt64List(list); 150 value = list; 151 break; 152 } 153 case ENUM: 154 { 155 List<Integer> list = new ArrayList<Integer>(); 156 reader.readEnumList(list); 157 unknownFields = 158 SchemaUtil.filterUnknownEnumList( 159 containerMessage, 160 fieldNumber, 161 list, 162 extension.descriptor.getEnumType(), 163 unknownFields, 164 unknownFieldSchema); 165 value = list; 166 break; 167 } 168 default: 169 throw new IllegalStateException( 170 "Type cannot be packed: " + extension.descriptor.getLiteType()); 171 } 172 extensions.setField(extension.descriptor, value); 173 } else { 174 Object value = null; 175 // Enum is a special case because unknown enum values will be put into UnknownFieldSetLite. 176 if (extension.getLiteType() == WireFormat.FieldType.ENUM) { 177 int number = reader.readInt32(); 178 Object enumValue = extension.descriptor.getEnumType().findValueByNumber(number); 179 if (enumValue == null) { 180 return SchemaUtil.storeUnknownEnum( 181 containerMessage, fieldNumber, number, unknownFields, unknownFieldSchema); 182 } 183 // Note, we store the integer value instead of the actual enum object in FieldSet. 184 // This is also different from full-runtime where we store EnumValueDescriptor. 185 value = number; 186 } else { 187 switch (extension.getLiteType()) { 188 case DOUBLE: 189 value = reader.readDouble(); 190 break; 191 case FLOAT: 192 value = reader.readFloat(); 193 break; 194 case INT64: 195 value = reader.readInt64(); 196 break; 197 case UINT64: 198 value = reader.readUInt64(); 199 break; 200 case INT32: 201 value = reader.readInt32(); 202 break; 203 case FIXED64: 204 value = reader.readFixed64(); 205 break; 206 case FIXED32: 207 value = reader.readFixed32(); 208 break; 209 case BOOL: 210 value = reader.readBool(); 211 break; 212 case BYTES: 213 value = reader.readBytes(); 214 break; 215 case UINT32: 216 value = reader.readUInt32(); 217 break; 218 case SFIXED32: 219 value = reader.readSFixed32(); 220 break; 221 case SFIXED64: 222 value = reader.readSFixed64(); 223 break; 224 case SINT32: 225 value = reader.readSInt32(); 226 break; 227 case SINT64: 228 value = reader.readSInt64(); 229 break; 230 231 case STRING: 232 value = reader.readString(); 233 break; 234 case GROUP: 235 // Special case handling for non-repeated sub-messages: merge in-place rather than 236 // building up new sub-messages and merging those, which is too slow. 237 // TODO: clean this up 238 if (!extension.isRepeated()) { 239 Object oldValue = extensions.getField(extension.descriptor); 240 if (oldValue instanceof GeneratedMessageLite) { 241 Schema extSchema = Protobuf.getInstance().schemaFor(oldValue); 242 if (!((GeneratedMessageLite<?, ?>) oldValue).isMutable()) { 243 Object newValue = extSchema.newInstance(); 244 extSchema.mergeFrom(newValue, oldValue); 245 extensions.setField(extension.descriptor, newValue); 246 oldValue = newValue; 247 } 248 reader.mergeGroupField(oldValue, extSchema, extensionRegistry); 249 return unknownFields; 250 } 251 } 252 value = 253 reader.readGroup( 254 extension.getMessageDefaultInstance().getClass(), extensionRegistry); 255 break; 256 257 case MESSAGE: 258 // Special case handling for non-repeated sub-messages: merge in-place rather than 259 // building up new sub-messages and merging those, which is too slow. 260 // TODO: clean this up 261 if (!extension.isRepeated()) { 262 Object oldValue = extensions.getField(extension.descriptor); 263 if (oldValue instanceof GeneratedMessageLite) { 264 Schema extSchema = Protobuf.getInstance().schemaFor(oldValue); 265 if (!((GeneratedMessageLite<?, ?>) oldValue).isMutable()) { 266 Object newValue = extSchema.newInstance(); 267 extSchema.mergeFrom(newValue, oldValue); 268 extensions.setField(extension.descriptor, newValue); 269 oldValue = newValue; 270 } 271 reader.mergeMessageField(oldValue, extSchema, extensionRegistry); 272 return unknownFields; 273 } 274 } 275 value = 276 reader.readMessage( 277 extension.getMessageDefaultInstance().getClass(), extensionRegistry); 278 break; 279 280 case ENUM: 281 throw new IllegalStateException("Shouldn't reach here."); 282 } 283 } 284 if (extension.isRepeated()) { 285 extensions.addRepeatedField(extension.descriptor, value); 286 } else { 287 switch (extension.getLiteType()) { 288 case MESSAGE: 289 case GROUP: 290 // TODO: this shouldn't be reachable, clean this up 291 Object oldValue = extensions.getField(extension.descriptor); 292 if (oldValue != null) { 293 value = Internal.mergeMessage(oldValue, value); 294 } 295 break; 296 default: 297 break; 298 } 299 extensions.setField(extension.descriptor, value); 300 } 301 } 302 return unknownFields; 303 } 304 305 @Override extensionNumber(Map.Entry<?, ?> extension)306 int extensionNumber(Map.Entry<?, ?> extension) { 307 GeneratedMessageLite.ExtensionDescriptor descriptor = 308 (GeneratedMessageLite.ExtensionDescriptor) extension.getKey(); 309 return descriptor.getNumber(); 310 } 311 312 @Override serializeExtension(Writer writer, Map.Entry<?, ?> extension)313 void serializeExtension(Writer writer, Map.Entry<?, ?> extension) throws IOException { 314 GeneratedMessageLite.ExtensionDescriptor descriptor = 315 (GeneratedMessageLite.ExtensionDescriptor) 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 SchemaUtil.writeInt32List( 415 descriptor.getNumber(), 416 (List<Integer>) extension.getValue(), 417 writer, 418 descriptor.isPacked()); 419 break; 420 case STRING: 421 SchemaUtil.writeStringList( 422 descriptor.getNumber(), (List<String>) extension.getValue(), writer); 423 break; 424 case GROUP: 425 { 426 List<?> data = (List<?>) extension.getValue(); 427 if (data != null && !data.isEmpty()) { 428 SchemaUtil.writeGroupList( 429 descriptor.getNumber(), 430 (List<?>) extension.getValue(), 431 writer, 432 Protobuf.getInstance().schemaFor(data.get(0).getClass())); 433 } 434 } 435 break; 436 case MESSAGE: 437 { 438 List<?> data = (List<?>) extension.getValue(); 439 if (data != null && !data.isEmpty()) { 440 SchemaUtil.writeMessageList( 441 descriptor.getNumber(), 442 (List<?>) extension.getValue(), 443 writer, 444 Protobuf.getInstance().schemaFor(data.get(0).getClass())); 445 } 446 } 447 break; 448 } 449 } else { 450 switch (descriptor.getLiteType()) { 451 case DOUBLE: 452 writer.writeDouble(descriptor.getNumber(), (Double) extension.getValue()); 453 break; 454 case FLOAT: 455 writer.writeFloat(descriptor.getNumber(), (Float) extension.getValue()); 456 break; 457 case INT64: 458 writer.writeInt64(descriptor.getNumber(), (Long) extension.getValue()); 459 break; 460 case UINT64: 461 writer.writeUInt64(descriptor.getNumber(), (Long) extension.getValue()); 462 break; 463 case INT32: 464 writer.writeInt32(descriptor.getNumber(), (Integer) extension.getValue()); 465 break; 466 case FIXED64: 467 writer.writeFixed64(descriptor.getNumber(), (Long) extension.getValue()); 468 break; 469 case FIXED32: 470 writer.writeFixed32(descriptor.getNumber(), (Integer) extension.getValue()); 471 break; 472 case BOOL: 473 writer.writeBool(descriptor.getNumber(), (Boolean) extension.getValue()); 474 break; 475 case BYTES: 476 writer.writeBytes(descriptor.getNumber(), (ByteString) extension.getValue()); 477 break; 478 case UINT32: 479 writer.writeUInt32(descriptor.getNumber(), (Integer) extension.getValue()); 480 break; 481 case SFIXED32: 482 writer.writeSFixed32(descriptor.getNumber(), (Integer) extension.getValue()); 483 break; 484 case SFIXED64: 485 writer.writeSFixed64(descriptor.getNumber(), (Long) extension.getValue()); 486 break; 487 case SINT32: 488 writer.writeSInt32(descriptor.getNumber(), (Integer) extension.getValue()); 489 break; 490 case SINT64: 491 writer.writeSInt64(descriptor.getNumber(), (Long) extension.getValue()); 492 break; 493 case ENUM: 494 writer.writeInt32(descriptor.getNumber(), (Integer) extension.getValue()); 495 break; 496 case STRING: 497 writer.writeString(descriptor.getNumber(), (String) extension.getValue()); 498 break; 499 case GROUP: 500 writer.writeGroup( 501 descriptor.getNumber(), 502 extension.getValue(), 503 Protobuf.getInstance().schemaFor(extension.getValue().getClass())); 504 break; 505 case MESSAGE: 506 writer.writeMessage( 507 descriptor.getNumber(), 508 extension.getValue(), 509 Protobuf.getInstance().schemaFor(extension.getValue().getClass())); 510 break; 511 } 512 } 513 } 514 515 @Override findExtensionByNumber( ExtensionRegistryLite extensionRegistry, MessageLite defaultInstance, int number)516 Object findExtensionByNumber( 517 ExtensionRegistryLite extensionRegistry, MessageLite defaultInstance, int number) { 518 return extensionRegistry.findLiteExtensionByNumber(defaultInstance, number); 519 } 520 521 @Override parseLengthPrefixedMessageSetItem( Reader reader, Object extensionObject, ExtensionRegistryLite extensionRegistry, FieldSet<ExtensionDescriptor> extensions)522 void parseLengthPrefixedMessageSetItem( 523 Reader reader, 524 Object extensionObject, 525 ExtensionRegistryLite extensionRegistry, 526 FieldSet<ExtensionDescriptor> extensions) 527 throws IOException { 528 GeneratedMessageLite.GeneratedExtension<?, ?> extension = 529 (GeneratedMessageLite.GeneratedExtension<?, ?>) extensionObject; 530 Object value = 531 reader.readMessage(extension.getMessageDefaultInstance().getClass(), extensionRegistry); 532 extensions.setField(extension.descriptor, value); 533 } 534 535 @Override parseMessageSetItem( ByteString data, Object extensionObject, ExtensionRegistryLite extensionRegistry, FieldSet<ExtensionDescriptor> extensions)536 void parseMessageSetItem( 537 ByteString data, 538 Object extensionObject, 539 ExtensionRegistryLite extensionRegistry, 540 FieldSet<ExtensionDescriptor> extensions) 541 throws IOException { 542 GeneratedMessageLite.GeneratedExtension<?, ?> extension = 543 (GeneratedMessageLite.GeneratedExtension<?, ?>) extensionObject; 544 545 MessageLite.Builder builder = extension.getMessageDefaultInstance().newBuilderForType(); 546 547 final CodedInputStream input = data.newCodedInput(); 548 549 builder.mergeFrom(input, extensionRegistry); 550 extensions.setField(extension.descriptor, builder.buildPartial()); 551 input.checkLastTagWas(0); 552 } 553 } 554