OLD | NEW |
(Empty) | |
| 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.AbstractMessageLite.Builder.LimitedInputStream; |
| 34 |
| 35 import java.io.IOException; |
| 36 import java.io.InputStream; |
| 37 import java.io.OutputStream; |
| 38 import java.util.ArrayList; |
| 39 import java.util.Arrays; |
| 40 import java.util.Collections; |
| 41 import java.util.List; |
| 42 import java.util.Map; |
| 43 import java.util.TreeMap; |
| 44 |
| 45 /** |
| 46 * {@code UnknownFieldSet} is used to keep track of fields which were seen when |
| 47 * parsing a protocol message but whose field numbers or types are unrecognized. |
| 48 * This most frequently occurs when new fields are added to a message type |
| 49 * and then messages containing those fields are read by old software that was |
| 50 * compiled before the new types were added. |
| 51 * |
| 52 * <p>Every {@link Message} contains an {@code UnknownFieldSet} (and every |
| 53 * {@link Message.Builder} contains an {@link Builder}). |
| 54 * |
| 55 * <p>Most users will never need to use this class. |
| 56 * |
| 57 * @author kenton@google.com Kenton Varda |
| 58 */ |
| 59 public final class UnknownFieldSet implements MessageLite { |
| 60 private UnknownFieldSet() {} |
| 61 |
| 62 /** Create a new {@link Builder}. */ |
| 63 public static Builder newBuilder() { |
| 64 return Builder.create(); |
| 65 } |
| 66 |
| 67 /** |
| 68 * Create a new {@link Builder} and initialize it to be a copy |
| 69 * of {@code copyFrom}. |
| 70 */ |
| 71 public static Builder newBuilder(final UnknownFieldSet copyFrom) { |
| 72 return newBuilder().mergeFrom(copyFrom); |
| 73 } |
| 74 |
| 75 /** Get an empty {@code UnknownFieldSet}. */ |
| 76 public static UnknownFieldSet getDefaultInstance() { |
| 77 return defaultInstance; |
| 78 } |
| 79 public UnknownFieldSet getDefaultInstanceForType() { |
| 80 return defaultInstance; |
| 81 } |
| 82 private static final UnknownFieldSet defaultInstance = |
| 83 new UnknownFieldSet(Collections.<Integer, Field>emptyMap()); |
| 84 |
| 85 /** |
| 86 * Construct an {@code UnknownFieldSet} around the given map. The map is |
| 87 * expected to be immutable. |
| 88 */ |
| 89 private UnknownFieldSet(final Map<Integer, Field> fields) { |
| 90 this.fields = fields; |
| 91 } |
| 92 private Map<Integer, Field> fields; |
| 93 |
| 94 |
| 95 @Override |
| 96 public boolean equals(final Object other) { |
| 97 if (this == other) { |
| 98 return true; |
| 99 } |
| 100 return (other instanceof UnknownFieldSet) && |
| 101 fields.equals(((UnknownFieldSet) other).fields); |
| 102 } |
| 103 |
| 104 @Override |
| 105 public int hashCode() { |
| 106 return fields.hashCode(); |
| 107 } |
| 108 |
| 109 /** Get a map of fields in the set by number. */ |
| 110 public Map<Integer, Field> asMap() { |
| 111 return fields; |
| 112 } |
| 113 |
| 114 /** Check if the given field number is present in the set. */ |
| 115 public boolean hasField(final int number) { |
| 116 return fields.containsKey(number); |
| 117 } |
| 118 |
| 119 /** |
| 120 * Get a field by number. Returns an empty field if not present. Never |
| 121 * returns {@code null}. |
| 122 */ |
| 123 public Field getField(final int number) { |
| 124 final Field result = fields.get(number); |
| 125 return (result == null) ? Field.getDefaultInstance() : result; |
| 126 } |
| 127 |
| 128 /** Serializes the set and writes it to {@code output}. */ |
| 129 public void writeTo(final CodedOutputStream output) throws IOException { |
| 130 for (final Map.Entry<Integer, Field> entry : fields.entrySet()) { |
| 131 entry.getValue().writeTo(entry.getKey(), output); |
| 132 } |
| 133 } |
| 134 |
| 135 /** |
| 136 * Converts the set to a string in protocol buffer text format. This is |
| 137 * just a trivial wrapper around |
| 138 * {@link TextFormat#printToString(UnknownFieldSet)}. |
| 139 */ |
| 140 @Override |
| 141 public String toString() { |
| 142 return TextFormat.printToString(this); |
| 143 } |
| 144 |
| 145 /** |
| 146 * Serializes the message to a {@code ByteString} and returns it. This is |
| 147 * just a trivial wrapper around {@link #writeTo(CodedOutputStream)}. |
| 148 */ |
| 149 public ByteString toByteString() { |
| 150 try { |
| 151 final ByteString.CodedBuilder out = |
| 152 ByteString.newCodedBuilder(getSerializedSize()); |
| 153 writeTo(out.getCodedOutput()); |
| 154 return out.build(); |
| 155 } catch (final IOException e) { |
| 156 throw new RuntimeException( |
| 157 "Serializing to a ByteString threw an IOException (should " + |
| 158 "never happen).", e); |
| 159 } |
| 160 } |
| 161 |
| 162 /** |
| 163 * Serializes the message to a {@code byte} array and returns it. This is |
| 164 * just a trivial wrapper around {@link #writeTo(CodedOutputStream)}. |
| 165 */ |
| 166 public byte[] toByteArray() { |
| 167 try { |
| 168 final byte[] result = new byte[getSerializedSize()]; |
| 169 final CodedOutputStream output = CodedOutputStream.newInstance(result); |
| 170 writeTo(output); |
| 171 output.checkNoSpaceLeft(); |
| 172 return result; |
| 173 } catch (final IOException e) { |
| 174 throw new RuntimeException( |
| 175 "Serializing to a byte array threw an IOException " + |
| 176 "(should never happen).", e); |
| 177 } |
| 178 } |
| 179 |
| 180 /** |
| 181 * Serializes the message and writes it to {@code output}. This is just a |
| 182 * trivial wrapper around {@link #writeTo(CodedOutputStream)}. |
| 183 */ |
| 184 public void writeTo(final OutputStream output) throws IOException { |
| 185 final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output); |
| 186 writeTo(codedOutput); |
| 187 codedOutput.flush(); |
| 188 } |
| 189 |
| 190 public void writeDelimitedTo(OutputStream output) throws IOException { |
| 191 final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output); |
| 192 codedOutput.writeRawVarint32(getSerializedSize()); |
| 193 writeTo(codedOutput); |
| 194 codedOutput.flush(); |
| 195 } |
| 196 |
| 197 /** Get the number of bytes required to encode this set. */ |
| 198 public int getSerializedSize() { |
| 199 int result = 0; |
| 200 for (final Map.Entry<Integer, Field> entry : fields.entrySet()) { |
| 201 result += entry.getValue().getSerializedSize(entry.getKey()); |
| 202 } |
| 203 return result; |
| 204 } |
| 205 |
| 206 /** |
| 207 * Serializes the set and writes it to {@code output} using |
| 208 * {@code MessageSet} wire format. |
| 209 */ |
| 210 public void writeAsMessageSetTo(final CodedOutputStream output) |
| 211 throws IOException { |
| 212 for (final Map.Entry<Integer, Field> entry : fields.entrySet()) { |
| 213 entry.getValue().writeAsMessageSetExtensionTo( |
| 214 entry.getKey(), output); |
| 215 } |
| 216 } |
| 217 |
| 218 /** |
| 219 * Get the number of bytes required to encode this set using |
| 220 * {@code MessageSet} wire format. |
| 221 */ |
| 222 public int getSerializedSizeAsMessageSet() { |
| 223 int result = 0; |
| 224 for (final Map.Entry<Integer, Field> entry : fields.entrySet()) { |
| 225 result += entry.getValue().getSerializedSizeAsMessageSetExtension( |
| 226 entry.getKey()); |
| 227 } |
| 228 return result; |
| 229 } |
| 230 |
| 231 public boolean isInitialized() { |
| 232 // UnknownFieldSets do not have required fields, so they are always |
| 233 // initialized. |
| 234 return true; |
| 235 } |
| 236 |
| 237 /** Parse an {@code UnknownFieldSet} from the given input stream. */ |
| 238 public static UnknownFieldSet parseFrom(final CodedInputStream input) |
| 239 throws IOException { |
| 240 return newBuilder().mergeFrom(input).build(); |
| 241 } |
| 242 |
| 243 /** Parse {@code data} as an {@code UnknownFieldSet} and return it. */ |
| 244 public static UnknownFieldSet parseFrom(final ByteString data) |
| 245 throws InvalidProtocolBufferException { |
| 246 return newBuilder().mergeFrom(data).build(); |
| 247 } |
| 248 |
| 249 /** Parse {@code data} as an {@code UnknownFieldSet} and return it. */ |
| 250 public static UnknownFieldSet parseFrom(final byte[] data) |
| 251 throws InvalidProtocolBufferException { |
| 252 return newBuilder().mergeFrom(data).build(); |
| 253 } |
| 254 |
| 255 /** Parse an {@code UnknownFieldSet} from {@code input} and return it. */ |
| 256 public static UnknownFieldSet parseFrom(final InputStream input) |
| 257 throws IOException { |
| 258 return newBuilder().mergeFrom(input).build(); |
| 259 } |
| 260 |
| 261 public Builder newBuilderForType() { |
| 262 return newBuilder(); |
| 263 } |
| 264 |
| 265 public Builder toBuilder() { |
| 266 return newBuilder().mergeFrom(this); |
| 267 } |
| 268 |
| 269 /** |
| 270 * Builder for {@link UnknownFieldSet}s. |
| 271 * |
| 272 * <p>Note that this class maintains {@link Field.Builder}s for all fields |
| 273 * in the set. Thus, adding one element to an existing {@link Field} does not |
| 274 * require making a copy. This is important for efficient parsing of |
| 275 * unknown repeated fields. However, it implies that {@link Field}s cannot |
| 276 * be constructed independently, nor can two {@link UnknownFieldSet}s share |
| 277 * the same {@code Field} object. |
| 278 * |
| 279 * <p>Use {@link UnknownFieldSet#newBuilder()} to construct a {@code Builder}. |
| 280 */ |
| 281 public static final class Builder implements MessageLite.Builder { |
| 282 // This constructor should never be called directly (except from 'create'). |
| 283 private Builder() {} |
| 284 |
| 285 private Map<Integer, Field> fields; |
| 286 |
| 287 // Optimization: We keep around a builder for the last field that was |
| 288 // modified so that we can efficiently add to it multiple times in a |
| 289 // row (important when parsing an unknown repeated field). |
| 290 private int lastFieldNumber; |
| 291 private Field.Builder lastField; |
| 292 |
| 293 private static Builder create() { |
| 294 Builder builder = new Builder(); |
| 295 builder.reinitialize(); |
| 296 return builder; |
| 297 } |
| 298 |
| 299 /** |
| 300 * Get a field builder for the given field number which includes any |
| 301 * values that already exist. |
| 302 */ |
| 303 private Field.Builder getFieldBuilder(final int number) { |
| 304 if (lastField != null) { |
| 305 if (number == lastFieldNumber) { |
| 306 return lastField; |
| 307 } |
| 308 // Note: addField() will reset lastField and lastFieldNumber. |
| 309 addField(lastFieldNumber, lastField.build()); |
| 310 } |
| 311 if (number == 0) { |
| 312 return null; |
| 313 } else { |
| 314 final Field existing = fields.get(number); |
| 315 lastFieldNumber = number; |
| 316 lastField = Field.newBuilder(); |
| 317 if (existing != null) { |
| 318 lastField.mergeFrom(existing); |
| 319 } |
| 320 return lastField; |
| 321 } |
| 322 } |
| 323 |
| 324 /** |
| 325 * Build the {@link UnknownFieldSet} and return it. |
| 326 * |
| 327 * <p>Once {@code build()} has been called, the {@code Builder} will no |
| 328 * longer be usable. Calling any method after {@code build()} will result |
| 329 * in undefined behavior and can cause a {@code NullPointerException} to be |
| 330 * thrown. |
| 331 */ |
| 332 public UnknownFieldSet build() { |
| 333 getFieldBuilder(0); // Force lastField to be built. |
| 334 final UnknownFieldSet result; |
| 335 if (fields.isEmpty()) { |
| 336 result = getDefaultInstance(); |
| 337 } else { |
| 338 result = new UnknownFieldSet(Collections.unmodifiableMap(fields)); |
| 339 } |
| 340 fields = null; |
| 341 return result; |
| 342 } |
| 343 |
| 344 public UnknownFieldSet buildPartial() { |
| 345 // No required fields, so this is the same as build(). |
| 346 return build(); |
| 347 } |
| 348 |
| 349 @Override |
| 350 public Builder clone() { |
| 351 getFieldBuilder(0); // Force lastField to be built. |
| 352 return UnknownFieldSet.newBuilder().mergeFrom( |
| 353 new UnknownFieldSet(fields)); |
| 354 } |
| 355 |
| 356 public UnknownFieldSet getDefaultInstanceForType() { |
| 357 return UnknownFieldSet.getDefaultInstance(); |
| 358 } |
| 359 |
| 360 private void reinitialize() { |
| 361 fields = Collections.emptyMap(); |
| 362 lastFieldNumber = 0; |
| 363 lastField = null; |
| 364 } |
| 365 |
| 366 /** Reset the builder to an empty set. */ |
| 367 public Builder clear() { |
| 368 reinitialize(); |
| 369 return this; |
| 370 } |
| 371 |
| 372 /** Clear fields from the set with a given field number. */ |
| 373 public Builder clearField(final int number) { |
| 374 if (number == 0) { |
| 375 throw new IllegalArgumentException("Zero is not a valid field number."); |
| 376 } |
| 377 if (lastField != null && lastFieldNumber == number) { |
| 378 // Discard this. |
| 379 lastField = null; |
| 380 lastFieldNumber = 0; |
| 381 } |
| 382 if (fields.containsKey(number)) { |
| 383 fields.remove(number); |
| 384 } |
| 385 return this; |
| 386 } |
| 387 |
| 388 /** |
| 389 * Merge the fields from {@code other} into this set. If a field number |
| 390 * exists in both sets, {@code other}'s values for that field will be |
| 391 * appended to the values in this set. |
| 392 */ |
| 393 public Builder mergeFrom(final UnknownFieldSet other) { |
| 394 if (other != getDefaultInstance()) { |
| 395 for (final Map.Entry<Integer, Field> entry : other.fields.entrySet()) { |
| 396 mergeField(entry.getKey(), entry.getValue()); |
| 397 } |
| 398 } |
| 399 return this; |
| 400 } |
| 401 |
| 402 /** |
| 403 * Add a field to the {@code UnknownFieldSet}. If a field with the same |
| 404 * number already exists, the two are merged. |
| 405 */ |
| 406 public Builder mergeField(final int number, final Field field) { |
| 407 if (number == 0) { |
| 408 throw new IllegalArgumentException("Zero is not a valid field number."); |
| 409 } |
| 410 if (hasField(number)) { |
| 411 getFieldBuilder(number).mergeFrom(field); |
| 412 } else { |
| 413 // Optimization: We could call getFieldBuilder(number).mergeFrom(field) |
| 414 // in this case, but that would create a copy of the Field object. |
| 415 // We'd rather reuse the one passed to us, so call addField() instead. |
| 416 addField(number, field); |
| 417 } |
| 418 return this; |
| 419 } |
| 420 |
| 421 /** |
| 422 * Convenience method for merging a new field containing a single varint |
| 423 * value. This is used in particular when an unknown enum value is |
| 424 * encountered. |
| 425 */ |
| 426 public Builder mergeVarintField(final int number, final int value) { |
| 427 if (number == 0) { |
| 428 throw new IllegalArgumentException("Zero is not a valid field number."); |
| 429 } |
| 430 getFieldBuilder(number).addVarint(value); |
| 431 return this; |
| 432 } |
| 433 |
| 434 |
| 435 /** |
| 436 * Convenience method for merging a length-delimited field. |
| 437 * |
| 438 * <p>For use by generated code only. |
| 439 */ |
| 440 public Builder mergeLengthDelimitedField( |
| 441 final int number, final ByteString value) { |
| 442 if (number == 0) { |
| 443 throw new IllegalArgumentException("Zero is not a valid field number."); |
| 444 } |
| 445 getFieldBuilder(number).addLengthDelimited(value); |
| 446 return this; |
| 447 } |
| 448 |
| 449 /** Check if the given field number is present in the set. */ |
| 450 public boolean hasField(final int number) { |
| 451 if (number == 0) { |
| 452 throw new IllegalArgumentException("Zero is not a valid field number."); |
| 453 } |
| 454 return number == lastFieldNumber || fields.containsKey(number); |
| 455 } |
| 456 |
| 457 /** |
| 458 * Add a field to the {@code UnknownFieldSet}. If a field with the same |
| 459 * number already exists, it is removed. |
| 460 */ |
| 461 public Builder addField(final int number, final Field field) { |
| 462 if (number == 0) { |
| 463 throw new IllegalArgumentException("Zero is not a valid field number."); |
| 464 } |
| 465 if (lastField != null && lastFieldNumber == number) { |
| 466 // Discard this. |
| 467 lastField = null; |
| 468 lastFieldNumber = 0; |
| 469 } |
| 470 if (fields.isEmpty()) { |
| 471 fields = new TreeMap<Integer,Field>(); |
| 472 } |
| 473 fields.put(number, field); |
| 474 return this; |
| 475 } |
| 476 |
| 477 /** |
| 478 * Get all present {@code Field}s as an immutable {@code Map}. If more |
| 479 * fields are added, the changes may or may not be reflected in this map. |
| 480 */ |
| 481 public Map<Integer, Field> asMap() { |
| 482 getFieldBuilder(0); // Force lastField to be built. |
| 483 return Collections.unmodifiableMap(fields); |
| 484 } |
| 485 |
| 486 /** |
| 487 * Parse an entire message from {@code input} and merge its fields into |
| 488 * this set. |
| 489 */ |
| 490 public Builder mergeFrom(final CodedInputStream input) throws IOException { |
| 491 while (true) { |
| 492 final int tag = input.readTag(); |
| 493 if (tag == 0 || !mergeFieldFrom(tag, input)) { |
| 494 break; |
| 495 } |
| 496 } |
| 497 return this; |
| 498 } |
| 499 |
| 500 /** |
| 501 * Parse a single field from {@code input} and merge it into this set. |
| 502 * @param tag The field's tag number, which was already parsed. |
| 503 * @return {@code false} if the tag is an end group tag. |
| 504 */ |
| 505 public boolean mergeFieldFrom(final int tag, final CodedInputStream input) |
| 506 throws IOException { |
| 507 final int number = WireFormat.getTagFieldNumber(tag); |
| 508 switch (WireFormat.getTagWireType(tag)) { |
| 509 case WireFormat.WIRETYPE_VARINT: |
| 510 getFieldBuilder(number).addVarint(input.readInt64()); |
| 511 return true; |
| 512 case WireFormat.WIRETYPE_FIXED64: |
| 513 getFieldBuilder(number).addFixed64(input.readFixed64()); |
| 514 return true; |
| 515 case WireFormat.WIRETYPE_LENGTH_DELIMITED: |
| 516 getFieldBuilder(number).addLengthDelimited(input.readBytes()); |
| 517 return true; |
| 518 case WireFormat.WIRETYPE_START_GROUP: |
| 519 final Builder subBuilder = newBuilder(); |
| 520 input.readGroup(number, subBuilder, |
| 521 ExtensionRegistry.getEmptyRegistry()); |
| 522 getFieldBuilder(number).addGroup(subBuilder.build()); |
| 523 return true; |
| 524 case WireFormat.WIRETYPE_END_GROUP: |
| 525 return false; |
| 526 case WireFormat.WIRETYPE_FIXED32: |
| 527 getFieldBuilder(number).addFixed32(input.readFixed32()); |
| 528 return true; |
| 529 default: |
| 530 throw InvalidProtocolBufferException.invalidWireType(); |
| 531 } |
| 532 } |
| 533 |
| 534 /** |
| 535 * Parse {@code data} as an {@code UnknownFieldSet} and merge it with the |
| 536 * set being built. This is just a small wrapper around |
| 537 * {@link #mergeFrom(CodedInputStream)}. |
| 538 */ |
| 539 public Builder mergeFrom(final ByteString data) |
| 540 throws InvalidProtocolBufferException { |
| 541 try { |
| 542 final CodedInputStream input = data.newCodedInput(); |
| 543 mergeFrom(input); |
| 544 input.checkLastTagWas(0); |
| 545 return this; |
| 546 } catch (final InvalidProtocolBufferException e) { |
| 547 throw e; |
| 548 } catch (final IOException e) { |
| 549 throw new RuntimeException( |
| 550 "Reading from a ByteString threw an IOException (should " + |
| 551 "never happen).", e); |
| 552 } |
| 553 } |
| 554 |
| 555 /** |
| 556 * Parse {@code data} as an {@code UnknownFieldSet} and merge it with the |
| 557 * set being built. This is just a small wrapper around |
| 558 * {@link #mergeFrom(CodedInputStream)}. |
| 559 */ |
| 560 public Builder mergeFrom(final byte[] data) |
| 561 throws InvalidProtocolBufferException { |
| 562 try { |
| 563 final CodedInputStream input = CodedInputStream.newInstance(data); |
| 564 mergeFrom(input); |
| 565 input.checkLastTagWas(0); |
| 566 return this; |
| 567 } catch (final InvalidProtocolBufferException e) { |
| 568 throw e; |
| 569 } catch (final IOException e) { |
| 570 throw new RuntimeException( |
| 571 "Reading from a byte array threw an IOException (should " + |
| 572 "never happen).", e); |
| 573 } |
| 574 } |
| 575 |
| 576 /** |
| 577 * Parse an {@code UnknownFieldSet} from {@code input} and merge it with the |
| 578 * set being built. This is just a small wrapper around |
| 579 * {@link #mergeFrom(CodedInputStream)}. |
| 580 */ |
| 581 public Builder mergeFrom(final InputStream input) throws IOException { |
| 582 final CodedInputStream codedInput = CodedInputStream.newInstance(input); |
| 583 mergeFrom(codedInput); |
| 584 codedInput.checkLastTagWas(0); |
| 585 return this; |
| 586 } |
| 587 |
| 588 public boolean mergeDelimitedFrom(InputStream input) |
| 589 throws IOException { |
| 590 final int firstByte = input.read(); |
| 591 if (firstByte == -1) { |
| 592 return false; |
| 593 } |
| 594 final int size = CodedInputStream.readRawVarint32(firstByte, input); |
| 595 final InputStream limitedInput = new LimitedInputStream(input, size); |
| 596 mergeFrom(limitedInput); |
| 597 return true; |
| 598 } |
| 599 |
| 600 public boolean mergeDelimitedFrom( |
| 601 InputStream input, |
| 602 ExtensionRegistryLite extensionRegistry) throws IOException { |
| 603 // UnknownFieldSet has no extensions. |
| 604 return mergeDelimitedFrom(input); |
| 605 } |
| 606 |
| 607 public Builder mergeFrom( |
| 608 CodedInputStream input, |
| 609 ExtensionRegistryLite extensionRegistry) throws IOException { |
| 610 // UnknownFieldSet has no extensions. |
| 611 return mergeFrom(input); |
| 612 } |
| 613 |
| 614 public Builder mergeFrom( |
| 615 ByteString data, |
| 616 ExtensionRegistryLite extensionRegistry) |
| 617 throws InvalidProtocolBufferException { |
| 618 // UnknownFieldSet has no extensions. |
| 619 return mergeFrom(data); |
| 620 } |
| 621 |
| 622 public Builder mergeFrom(byte[] data, int off, int len) |
| 623 throws InvalidProtocolBufferException { |
| 624 try { |
| 625 final CodedInputStream input = |
| 626 CodedInputStream.newInstance(data, off, len); |
| 627 mergeFrom(input); |
| 628 input.checkLastTagWas(0); |
| 629 return this; |
| 630 } catch (InvalidProtocolBufferException e) { |
| 631 throw e; |
| 632 } catch (IOException e) { |
| 633 throw new RuntimeException( |
| 634 "Reading from a byte array threw an IOException (should " + |
| 635 "never happen).", e); |
| 636 } |
| 637 } |
| 638 |
| 639 public Builder mergeFrom( |
| 640 byte[] data, |
| 641 ExtensionRegistryLite extensionRegistry) |
| 642 throws InvalidProtocolBufferException { |
| 643 // UnknownFieldSet has no extensions. |
| 644 return mergeFrom(data); |
| 645 } |
| 646 |
| 647 public Builder mergeFrom( |
| 648 byte[] data, int off, int len, |
| 649 ExtensionRegistryLite extensionRegistry) |
| 650 throws InvalidProtocolBufferException { |
| 651 // UnknownFieldSet has no extensions. |
| 652 return mergeFrom(data, off, len); |
| 653 } |
| 654 |
| 655 public Builder mergeFrom( |
| 656 InputStream input, |
| 657 ExtensionRegistryLite extensionRegistry) throws IOException { |
| 658 // UnknownFieldSet has no extensions. |
| 659 return mergeFrom(input); |
| 660 } |
| 661 |
| 662 public boolean isInitialized() { |
| 663 // UnknownFieldSets do not have required fields, so they are always |
| 664 // initialized. |
| 665 return true; |
| 666 } |
| 667 } |
| 668 |
| 669 /** |
| 670 * Represents a single field in an {@code UnknownFieldSet}. |
| 671 * |
| 672 * <p>A {@code Field} consists of five lists of values. The lists correspond |
| 673 * to the five "wire types" used in the protocol buffer binary format. |
| 674 * The wire type of each field can be determined from the encoded form alone, |
| 675 * without knowing the field's declared type. So, we are able to parse |
| 676 * unknown values at least this far and separate them. Normally, only one |
| 677 * of the five lists will contain any values, since it is impossible to |
| 678 * define a valid message type that declares two different types for the |
| 679 * same field number. However, the code is designed to allow for the case |
| 680 * where the same unknown field number is encountered using multiple different |
| 681 * wire types. |
| 682 * |
| 683 * <p>{@code Field} is an immutable class. To construct one, you must use a |
| 684 * {@link Builder}. |
| 685 * |
| 686 * @see UnknownFieldSet |
| 687 */ |
| 688 public static final class Field { |
| 689 private Field() {} |
| 690 |
| 691 /** Construct a new {@link Builder}. */ |
| 692 public static Builder newBuilder() { |
| 693 return Builder.create(); |
| 694 } |
| 695 |
| 696 /** |
| 697 * Construct a new {@link Builder} and initialize it to a copy of |
| 698 * {@code copyFrom}. |
| 699 */ |
| 700 public static Builder newBuilder(final Field copyFrom) { |
| 701 return newBuilder().mergeFrom(copyFrom); |
| 702 } |
| 703 |
| 704 /** Get an empty {@code Field}. */ |
| 705 public static Field getDefaultInstance() { |
| 706 return fieldDefaultInstance; |
| 707 } |
| 708 private static final Field fieldDefaultInstance = newBuilder().build(); |
| 709 |
| 710 /** Get the list of varint values for this field. */ |
| 711 public List<Long> getVarintList() { return varint; } |
| 712 |
| 713 /** Get the list of fixed32 values for this field. */ |
| 714 public List<Integer> getFixed32List() { return fixed32; } |
| 715 |
| 716 /** Get the list of fixed64 values for this field. */ |
| 717 public List<Long> getFixed64List() { return fixed64; } |
| 718 |
| 719 /** Get the list of length-delimited values for this field. */ |
| 720 public List<ByteString> getLengthDelimitedList() { return lengthDelimited; } |
| 721 |
| 722 /** |
| 723 * Get the list of embedded group values for this field. These are |
| 724 * represented using {@link UnknownFieldSet}s rather than {@link Message}s |
| 725 * since the group's type is presumably unknown. |
| 726 */ |
| 727 public List<UnknownFieldSet> getGroupList() { return group; } |
| 728 |
| 729 @Override |
| 730 public boolean equals(final Object other) { |
| 731 if (this == other) { |
| 732 return true; |
| 733 } |
| 734 if (!(other instanceof Field)) { |
| 735 return false; |
| 736 } |
| 737 return Arrays.equals(getIdentityArray(), |
| 738 ((Field) other).getIdentityArray()); |
| 739 } |
| 740 |
| 741 @Override |
| 742 public int hashCode() { |
| 743 return Arrays.hashCode(getIdentityArray()); |
| 744 } |
| 745 |
| 746 /** |
| 747 * Returns the array of objects to be used to uniquely identify this |
| 748 * {@link Field} instance. |
| 749 */ |
| 750 private Object[] getIdentityArray() { |
| 751 return new Object[] { |
| 752 varint, |
| 753 fixed32, |
| 754 fixed64, |
| 755 lengthDelimited, |
| 756 group}; |
| 757 } |
| 758 |
| 759 /** |
| 760 * Serializes the field, including field number, and writes it to |
| 761 * {@code output}. |
| 762 */ |
| 763 public void writeTo(final int fieldNumber, final CodedOutputStream output) |
| 764 throws IOException { |
| 765 for (final long value : varint) { |
| 766 output.writeUInt64(fieldNumber, value); |
| 767 } |
| 768 for (final int value : fixed32) { |
| 769 output.writeFixed32(fieldNumber, value); |
| 770 } |
| 771 for (final long value : fixed64) { |
| 772 output.writeFixed64(fieldNumber, value); |
| 773 } |
| 774 for (final ByteString value : lengthDelimited) { |
| 775 output.writeBytes(fieldNumber, value); |
| 776 } |
| 777 for (final UnknownFieldSet value : group) { |
| 778 output.writeGroup(fieldNumber, value); |
| 779 } |
| 780 } |
| 781 |
| 782 /** |
| 783 * Get the number of bytes required to encode this field, including field |
| 784 * number. |
| 785 */ |
| 786 public int getSerializedSize(final int fieldNumber) { |
| 787 int result = 0; |
| 788 for (final long value : varint) { |
| 789 result += CodedOutputStream.computeUInt64Size(fieldNumber, value); |
| 790 } |
| 791 for (final int value : fixed32) { |
| 792 result += CodedOutputStream.computeFixed32Size(fieldNumber, value); |
| 793 } |
| 794 for (final long value : fixed64) { |
| 795 result += CodedOutputStream.computeFixed64Size(fieldNumber, value); |
| 796 } |
| 797 for (final ByteString value : lengthDelimited) { |
| 798 result += CodedOutputStream.computeBytesSize(fieldNumber, value); |
| 799 } |
| 800 for (final UnknownFieldSet value : group) { |
| 801 result += CodedOutputStream.computeGroupSize(fieldNumber, value); |
| 802 } |
| 803 return result; |
| 804 } |
| 805 |
| 806 /** |
| 807 * Serializes the field, including field number, and writes it to |
| 808 * {@code output}, using {@code MessageSet} wire format. |
| 809 */ |
| 810 public void writeAsMessageSetExtensionTo( |
| 811 final int fieldNumber, |
| 812 final CodedOutputStream output) |
| 813 throws IOException { |
| 814 for (final ByteString value : lengthDelimited) { |
| 815 output.writeRawMessageSetExtension(fieldNumber, value); |
| 816 } |
| 817 } |
| 818 |
| 819 /** |
| 820 * Get the number of bytes required to encode this field, including field |
| 821 * number, using {@code MessageSet} wire format. |
| 822 */ |
| 823 public int getSerializedSizeAsMessageSetExtension(final int fieldNumber) { |
| 824 int result = 0; |
| 825 for (final ByteString value : lengthDelimited) { |
| 826 result += CodedOutputStream.computeRawMessageSetExtensionSize( |
| 827 fieldNumber, value); |
| 828 } |
| 829 return result; |
| 830 } |
| 831 |
| 832 private List<Long> varint; |
| 833 private List<Integer> fixed32; |
| 834 private List<Long> fixed64; |
| 835 private List<ByteString> lengthDelimited; |
| 836 private List<UnknownFieldSet> group; |
| 837 |
| 838 /** |
| 839 * Used to build a {@link Field} within an {@link UnknownFieldSet}. |
| 840 * |
| 841 * <p>Use {@link Field#newBuilder()} to construct a {@code Builder}. |
| 842 */ |
| 843 public static final class Builder { |
| 844 // This constructor should never be called directly (except from 'create')
. |
| 845 private Builder() {} |
| 846 |
| 847 private static Builder create() { |
| 848 Builder builder = new Builder(); |
| 849 builder.result = new Field(); |
| 850 return builder; |
| 851 } |
| 852 |
| 853 private Field result; |
| 854 |
| 855 /** |
| 856 * Build the field. After {@code build()} has been called, the |
| 857 * {@code Builder} is no longer usable. Calling any other method will |
| 858 * result in undefined behavior and can cause a |
| 859 * {@code NullPointerException} to be thrown. |
| 860 */ |
| 861 public Field build() { |
| 862 if (result.varint == null) { |
| 863 result.varint = Collections.emptyList(); |
| 864 } else { |
| 865 result.varint = Collections.unmodifiableList(result.varint); |
| 866 } |
| 867 if (result.fixed32 == null) { |
| 868 result.fixed32 = Collections.emptyList(); |
| 869 } else { |
| 870 result.fixed32 = Collections.unmodifiableList(result.fixed32); |
| 871 } |
| 872 if (result.fixed64 == null) { |
| 873 result.fixed64 = Collections.emptyList(); |
| 874 } else { |
| 875 result.fixed64 = Collections.unmodifiableList(result.fixed64); |
| 876 } |
| 877 if (result.lengthDelimited == null) { |
| 878 result.lengthDelimited = Collections.emptyList(); |
| 879 } else { |
| 880 result.lengthDelimited = |
| 881 Collections.unmodifiableList(result.lengthDelimited); |
| 882 } |
| 883 if (result.group == null) { |
| 884 result.group = Collections.emptyList(); |
| 885 } else { |
| 886 result.group = Collections.unmodifiableList(result.group); |
| 887 } |
| 888 |
| 889 final Field returnMe = result; |
| 890 result = null; |
| 891 return returnMe; |
| 892 } |
| 893 |
| 894 /** Discard the field's contents. */ |
| 895 public Builder clear() { |
| 896 result = new Field(); |
| 897 return this; |
| 898 } |
| 899 |
| 900 /** |
| 901 * Merge the values in {@code other} into this field. For each list |
| 902 * of values, {@code other}'s values are append to the ones in this |
| 903 * field. |
| 904 */ |
| 905 public Builder mergeFrom(final Field other) { |
| 906 if (!other.varint.isEmpty()) { |
| 907 if (result.varint == null) { |
| 908 result.varint = new ArrayList<Long>(); |
| 909 } |
| 910 result.varint.addAll(other.varint); |
| 911 } |
| 912 if (!other.fixed32.isEmpty()) { |
| 913 if (result.fixed32 == null) { |
| 914 result.fixed32 = new ArrayList<Integer>(); |
| 915 } |
| 916 result.fixed32.addAll(other.fixed32); |
| 917 } |
| 918 if (!other.fixed64.isEmpty()) { |
| 919 if (result.fixed64 == null) { |
| 920 result.fixed64 = new ArrayList<Long>(); |
| 921 } |
| 922 result.fixed64.addAll(other.fixed64); |
| 923 } |
| 924 if (!other.lengthDelimited.isEmpty()) { |
| 925 if (result.lengthDelimited == null) { |
| 926 result.lengthDelimited = new ArrayList<ByteString>(); |
| 927 } |
| 928 result.lengthDelimited.addAll(other.lengthDelimited); |
| 929 } |
| 930 if (!other.group.isEmpty()) { |
| 931 if (result.group == null) { |
| 932 result.group = new ArrayList<UnknownFieldSet>(); |
| 933 } |
| 934 result.group.addAll(other.group); |
| 935 } |
| 936 return this; |
| 937 } |
| 938 |
| 939 /** Add a varint value. */ |
| 940 public Builder addVarint(final long value) { |
| 941 if (result.varint == null) { |
| 942 result.varint = new ArrayList<Long>(); |
| 943 } |
| 944 result.varint.add(value); |
| 945 return this; |
| 946 } |
| 947 |
| 948 /** Add a fixed32 value. */ |
| 949 public Builder addFixed32(final int value) { |
| 950 if (result.fixed32 == null) { |
| 951 result.fixed32 = new ArrayList<Integer>(); |
| 952 } |
| 953 result.fixed32.add(value); |
| 954 return this; |
| 955 } |
| 956 |
| 957 /** Add a fixed64 value. */ |
| 958 public Builder addFixed64(final long value) { |
| 959 if (result.fixed64 == null) { |
| 960 result.fixed64 = new ArrayList<Long>(); |
| 961 } |
| 962 result.fixed64.add(value); |
| 963 return this; |
| 964 } |
| 965 |
| 966 /** Add a length-delimited value. */ |
| 967 public Builder addLengthDelimited(final ByteString value) { |
| 968 if (result.lengthDelimited == null) { |
| 969 result.lengthDelimited = new ArrayList<ByteString>(); |
| 970 } |
| 971 result.lengthDelimited.add(value); |
| 972 return this; |
| 973 } |
| 974 |
| 975 /** Add an embedded group. */ |
| 976 public Builder addGroup(final UnknownFieldSet value) { |
| 977 if (result.group == null) { |
| 978 result.group = new ArrayList<UnknownFieldSet>(); |
| 979 } |
| 980 result.group.add(value); |
| 981 return this; |
| 982 } |
| 983 } |
| 984 } |
| 985 |
| 986 /** |
| 987 * Parser to implement MessageLite interface. |
| 988 */ |
| 989 public static final class Parser extends AbstractParser<UnknownFieldSet> { |
| 990 public UnknownFieldSet parsePartialFrom( |
| 991 CodedInputStream input, ExtensionRegistryLite extensionRegistry) |
| 992 throws InvalidProtocolBufferException { |
| 993 Builder builder = newBuilder(); |
| 994 try { |
| 995 builder.mergeFrom(input); |
| 996 } catch (InvalidProtocolBufferException e) { |
| 997 throw e.setUnfinishedMessage(builder.buildPartial()); |
| 998 } catch (IOException e) { |
| 999 throw new InvalidProtocolBufferException(e.getMessage()) |
| 1000 .setUnfinishedMessage(builder.buildPartial()); |
| 1001 } |
| 1002 return builder.buildPartial(); |
| 1003 } |
| 1004 } |
| 1005 |
| 1006 private static final Parser PARSER = new Parser(); |
| 1007 public final Parser getParserForType() { |
| 1008 return PARSER; |
| 1009 } |
| 1010 } |
OLD | NEW |