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 static com.google.protobuf.Internal.checkNotNull; 34 import static com.google.protobuf.WireFormat.WIRETYPE_LENGTH_DELIMITED; 35 36 import java.io.IOException; 37 import java.util.Arrays; 38 import java.util.List; 39 import java.util.Map; 40 41 /** An adapter between the {@link Writer} interface and {@link CodedOutputStream}. */ 42 @ExperimentalApi 43 final class CodedOutputStreamWriter implements Writer { 44 private final CodedOutputStream output; 45 forCodedOutput(CodedOutputStream output)46 public static CodedOutputStreamWriter forCodedOutput(CodedOutputStream output) { 47 if (output.wrapper != null) { 48 return output.wrapper; 49 } 50 return new CodedOutputStreamWriter(output); 51 } 52 CodedOutputStreamWriter(CodedOutputStream output)53 private CodedOutputStreamWriter(CodedOutputStream output) { 54 this.output = checkNotNull(output, "output"); 55 this.output.wrapper = this; 56 } 57 58 @Override fieldOrder()59 public FieldOrder fieldOrder() { 60 return FieldOrder.ASCENDING; 61 } 62 getTotalBytesWritten()63 public int getTotalBytesWritten() { 64 return output.getTotalBytesWritten(); 65 } 66 67 @Override writeSFixed32(int fieldNumber, int value)68 public void writeSFixed32(int fieldNumber, int value) throws IOException { 69 output.writeSFixed32(fieldNumber, value); 70 } 71 72 @Override writeInt64(int fieldNumber, long value)73 public void writeInt64(int fieldNumber, long value) throws IOException { 74 output.writeInt64(fieldNumber, value); 75 } 76 77 @Override writeSFixed64(int fieldNumber, long value)78 public void writeSFixed64(int fieldNumber, long value) throws IOException { 79 output.writeSFixed64(fieldNumber, value); 80 } 81 82 @Override writeFloat(int fieldNumber, float value)83 public void writeFloat(int fieldNumber, float value) throws IOException { 84 output.writeFloat(fieldNumber, value); 85 } 86 87 @Override writeDouble(int fieldNumber, double value)88 public void writeDouble(int fieldNumber, double value) throws IOException { 89 output.writeDouble(fieldNumber, value); 90 } 91 92 @Override writeEnum(int fieldNumber, int value)93 public void writeEnum(int fieldNumber, int value) throws IOException { 94 output.writeEnum(fieldNumber, value); 95 } 96 97 @Override writeUInt64(int fieldNumber, long value)98 public void writeUInt64(int fieldNumber, long value) throws IOException { 99 output.writeUInt64(fieldNumber, value); 100 } 101 102 @Override writeInt32(int fieldNumber, int value)103 public void writeInt32(int fieldNumber, int value) throws IOException { 104 output.writeInt32(fieldNumber, value); 105 } 106 107 @Override writeFixed64(int fieldNumber, long value)108 public void writeFixed64(int fieldNumber, long value) throws IOException { 109 output.writeFixed64(fieldNumber, value); 110 } 111 112 @Override writeFixed32(int fieldNumber, int value)113 public void writeFixed32(int fieldNumber, int value) throws IOException { 114 output.writeFixed32(fieldNumber, value); 115 } 116 117 @Override writeBool(int fieldNumber, boolean value)118 public void writeBool(int fieldNumber, boolean value) throws IOException { 119 output.writeBool(fieldNumber, value); 120 } 121 122 @Override writeString(int fieldNumber, String value)123 public void writeString(int fieldNumber, String value) throws IOException { 124 output.writeString(fieldNumber, value); 125 } 126 127 @Override writeBytes(int fieldNumber, ByteString value)128 public void writeBytes(int fieldNumber, ByteString value) throws IOException { 129 output.writeBytes(fieldNumber, value); 130 } 131 132 @Override writeUInt32(int fieldNumber, int value)133 public void writeUInt32(int fieldNumber, int value) throws IOException { 134 output.writeUInt32(fieldNumber, value); 135 } 136 137 @Override writeSInt32(int fieldNumber, int value)138 public void writeSInt32(int fieldNumber, int value) throws IOException { 139 output.writeSInt32(fieldNumber, value); 140 } 141 142 @Override writeSInt64(int fieldNumber, long value)143 public void writeSInt64(int fieldNumber, long value) throws IOException { 144 output.writeSInt64(fieldNumber, value); 145 } 146 147 @Override writeMessage(int fieldNumber, Object value)148 public void writeMessage(int fieldNumber, Object value) throws IOException { 149 output.writeMessage(fieldNumber, (MessageLite) value); 150 } 151 152 @Override writeMessage(int fieldNumber, Object value, Schema schema)153 public void writeMessage(int fieldNumber, Object value, Schema schema) throws IOException { 154 output.writeMessage(fieldNumber, (MessageLite) value, schema); 155 } 156 157 @Override writeGroup(int fieldNumber, Object value)158 public void writeGroup(int fieldNumber, Object value) throws IOException { 159 output.writeGroup(fieldNumber, (MessageLite) value); 160 } 161 162 @Override writeGroup(int fieldNumber, Object value, Schema schema)163 public void writeGroup(int fieldNumber, Object value, Schema schema) throws IOException { 164 output.writeGroup(fieldNumber, (MessageLite) value, schema); 165 } 166 167 @Override writeStartGroup(int fieldNumber)168 public void writeStartGroup(int fieldNumber) throws IOException { 169 output.writeTag(fieldNumber, WireFormat.WIRETYPE_START_GROUP); 170 } 171 172 @Override writeEndGroup(int fieldNumber)173 public void writeEndGroup(int fieldNumber) throws IOException { 174 output.writeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP); 175 } 176 177 @Override writeMessageSetItem(int fieldNumber, Object value)178 public final void writeMessageSetItem(int fieldNumber, Object value) throws IOException { 179 if (value instanceof ByteString) { 180 output.writeRawMessageSetExtension(fieldNumber, (ByteString) value); 181 } else { 182 output.writeMessageSetExtension(fieldNumber, (MessageLite) value); 183 } 184 } 185 186 @Override writeInt32List(int fieldNumber, List<Integer> value, boolean packed)187 public void writeInt32List(int fieldNumber, List<Integer> value, boolean packed) 188 throws IOException { 189 if (packed) { 190 output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); 191 192 // Compute and write the length of the data. 193 int dataSize = 0; 194 for (int i = 0; i < value.size(); ++i) { 195 dataSize += CodedOutputStream.computeInt32SizeNoTag(value.get(i)); 196 } 197 output.writeUInt32NoTag(dataSize); 198 199 // Write the data itself, without any tags. 200 for (int i = 0; i < value.size(); ++i) { 201 output.writeInt32NoTag(value.get(i)); 202 } 203 } else { 204 for (int i = 0; i < value.size(); ++i) { 205 output.writeInt32(fieldNumber, value.get(i)); 206 } 207 } 208 } 209 210 @Override writeFixed32List(int fieldNumber, List<Integer> value, boolean packed)211 public void writeFixed32List(int fieldNumber, List<Integer> value, boolean packed) 212 throws IOException { 213 if (packed) { 214 output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); 215 216 // Compute and write the length of the data. 217 int dataSize = 0; 218 for (int i = 0; i < value.size(); ++i) { 219 dataSize += CodedOutputStream.computeFixed32SizeNoTag(value.get(i)); 220 } 221 output.writeUInt32NoTag(dataSize); 222 223 // Write the data itself, without any tags. 224 for (int i = 0; i < value.size(); ++i) { 225 output.writeFixed32NoTag(value.get(i)); 226 } 227 } else { 228 for (int i = 0; i < value.size(); ++i) { 229 output.writeFixed32(fieldNumber, value.get(i)); 230 } 231 } 232 } 233 234 @Override writeInt64List(int fieldNumber, List<Long> value, boolean packed)235 public void writeInt64List(int fieldNumber, List<Long> value, boolean packed) throws IOException { 236 if (packed) { 237 output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); 238 239 // Compute and write the length of the data. 240 int dataSize = 0; 241 for (int i = 0; i < value.size(); ++i) { 242 dataSize += CodedOutputStream.computeInt64SizeNoTag(value.get(i)); 243 } 244 output.writeUInt32NoTag(dataSize); 245 246 // Write the data itself, without any tags. 247 for (int i = 0; i < value.size(); ++i) { 248 output.writeInt64NoTag(value.get(i)); 249 } 250 } else { 251 for (int i = 0; i < value.size(); ++i) { 252 output.writeInt64(fieldNumber, value.get(i)); 253 } 254 } 255 } 256 257 @Override writeUInt64List(int fieldNumber, List<Long> value, boolean packed)258 public void writeUInt64List(int fieldNumber, List<Long> value, boolean packed) 259 throws IOException { 260 if (packed) { 261 output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); 262 263 // Compute and write the length of the data. 264 int dataSize = 0; 265 for (int i = 0; i < value.size(); ++i) { 266 dataSize += CodedOutputStream.computeUInt64SizeNoTag(value.get(i)); 267 } 268 output.writeUInt32NoTag(dataSize); 269 270 // Write the data itself, without any tags. 271 for (int i = 0; i < value.size(); ++i) { 272 output.writeUInt64NoTag(value.get(i)); 273 } 274 } else { 275 for (int i = 0; i < value.size(); ++i) { 276 output.writeUInt64(fieldNumber, value.get(i)); 277 } 278 } 279 } 280 281 @Override writeFixed64List(int fieldNumber, List<Long> value, boolean packed)282 public void writeFixed64List(int fieldNumber, List<Long> value, boolean packed) 283 throws IOException { 284 if (packed) { 285 output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); 286 287 // Compute and write the length of the data. 288 int dataSize = 0; 289 for (int i = 0; i < value.size(); ++i) { 290 dataSize += CodedOutputStream.computeFixed64SizeNoTag(value.get(i)); 291 } 292 output.writeUInt32NoTag(dataSize); 293 294 // Write the data itself, without any tags. 295 for (int i = 0; i < value.size(); ++i) { 296 output.writeFixed64NoTag(value.get(i)); 297 } 298 } else { 299 for (int i = 0; i < value.size(); ++i) { 300 output.writeFixed64(fieldNumber, value.get(i)); 301 } 302 } 303 } 304 305 @Override writeFloatList(int fieldNumber, List<Float> value, boolean packed)306 public void writeFloatList(int fieldNumber, List<Float> value, boolean packed) 307 throws IOException { 308 if (packed) { 309 output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); 310 311 // Compute and write the length of the data. 312 int dataSize = 0; 313 for (int i = 0; i < value.size(); ++i) { 314 dataSize += CodedOutputStream.computeFloatSizeNoTag(value.get(i)); 315 } 316 output.writeUInt32NoTag(dataSize); 317 318 // Write the data itself, without any tags. 319 for (int i = 0; i < value.size(); ++i) { 320 output.writeFloatNoTag(value.get(i)); 321 } 322 } else { 323 for (int i = 0; i < value.size(); ++i) { 324 output.writeFloat(fieldNumber, value.get(i)); 325 } 326 } 327 } 328 329 @Override writeDoubleList(int fieldNumber, List<Double> value, boolean packed)330 public void writeDoubleList(int fieldNumber, List<Double> value, boolean packed) 331 throws IOException { 332 if (packed) { 333 output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); 334 335 // Compute and write the length of the data. 336 int dataSize = 0; 337 for (int i = 0; i < value.size(); ++i) { 338 dataSize += CodedOutputStream.computeDoubleSizeNoTag(value.get(i)); 339 } 340 output.writeUInt32NoTag(dataSize); 341 342 // Write the data itself, without any tags. 343 for (int i = 0; i < value.size(); ++i) { 344 output.writeDoubleNoTag(value.get(i)); 345 } 346 } else { 347 for (int i = 0; i < value.size(); ++i) { 348 output.writeDouble(fieldNumber, value.get(i)); 349 } 350 } 351 } 352 353 @Override writeEnumList(int fieldNumber, List<Integer> value, boolean packed)354 public void writeEnumList(int fieldNumber, List<Integer> value, boolean packed) 355 throws IOException { 356 if (packed) { 357 output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); 358 359 // Compute and write the length of the data. 360 int dataSize = 0; 361 for (int i = 0; i < value.size(); ++i) { 362 dataSize += CodedOutputStream.computeEnumSizeNoTag(value.get(i)); 363 } 364 output.writeUInt32NoTag(dataSize); 365 366 // Write the data itself, without any tags. 367 for (int i = 0; i < value.size(); ++i) { 368 output.writeEnumNoTag(value.get(i)); 369 } 370 } else { 371 for (int i = 0; i < value.size(); ++i) { 372 output.writeEnum(fieldNumber, value.get(i)); 373 } 374 } 375 } 376 377 @Override writeBoolList(int fieldNumber, List<Boolean> value, boolean packed)378 public void writeBoolList(int fieldNumber, List<Boolean> value, boolean packed) 379 throws IOException { 380 if (packed) { 381 output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); 382 383 // Compute and write the length of the data. 384 int dataSize = 0; 385 for (int i = 0; i < value.size(); ++i) { 386 dataSize += CodedOutputStream.computeBoolSizeNoTag(value.get(i)); 387 } 388 output.writeUInt32NoTag(dataSize); 389 390 // Write the data itself, without any tags. 391 for (int i = 0; i < value.size(); ++i) { 392 output.writeBoolNoTag(value.get(i)); 393 } 394 } else { 395 for (int i = 0; i < value.size(); ++i) { 396 output.writeBool(fieldNumber, value.get(i)); 397 } 398 } 399 } 400 401 @Override writeStringList(int fieldNumber, List<String> value)402 public void writeStringList(int fieldNumber, List<String> value) throws IOException { 403 if (value instanceof LazyStringList) { 404 final LazyStringList lazyList = (LazyStringList) value; 405 for (int i = 0; i < value.size(); ++i) { 406 writeLazyString(fieldNumber, lazyList.getRaw(i)); 407 } 408 } else { 409 for (int i = 0; i < value.size(); ++i) { 410 output.writeString(fieldNumber, value.get(i)); 411 } 412 } 413 } 414 writeLazyString(int fieldNumber, Object value)415 private void writeLazyString(int fieldNumber, Object value) throws IOException { 416 if (value instanceof String) { 417 output.writeString(fieldNumber, (String) value); 418 } else { 419 output.writeBytes(fieldNumber, (ByteString) value); 420 } 421 } 422 423 @Override writeBytesList(int fieldNumber, List<ByteString> value)424 public void writeBytesList(int fieldNumber, List<ByteString> value) throws IOException { 425 for (int i = 0; i < value.size(); ++i) { 426 output.writeBytes(fieldNumber, value.get(i)); 427 } 428 } 429 430 @Override writeUInt32List(int fieldNumber, List<Integer> value, boolean packed)431 public void writeUInt32List(int fieldNumber, List<Integer> value, boolean packed) 432 throws IOException { 433 if (packed) { 434 output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); 435 436 // Compute and write the length of the data. 437 int dataSize = 0; 438 for (int i = 0; i < value.size(); ++i) { 439 dataSize += CodedOutputStream.computeUInt32SizeNoTag(value.get(i)); 440 } 441 output.writeUInt32NoTag(dataSize); 442 443 // Write the data itself, without any tags. 444 for (int i = 0; i < value.size(); ++i) { 445 output.writeUInt32NoTag(value.get(i)); 446 } 447 } else { 448 for (int i = 0; i < value.size(); ++i) { 449 output.writeUInt32(fieldNumber, value.get(i)); 450 } 451 } 452 } 453 454 @Override writeSFixed32List(int fieldNumber, List<Integer> value, boolean packed)455 public void writeSFixed32List(int fieldNumber, List<Integer> value, boolean packed) 456 throws IOException { 457 if (packed) { 458 output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); 459 460 // Compute and write the length of the data. 461 int dataSize = 0; 462 for (int i = 0; i < value.size(); ++i) { 463 dataSize += CodedOutputStream.computeSFixed32SizeNoTag(value.get(i)); 464 } 465 output.writeUInt32NoTag(dataSize); 466 467 // Write the data itself, without any tags. 468 for (int i = 0; i < value.size(); ++i) { 469 output.writeSFixed32NoTag(value.get(i)); 470 } 471 } else { 472 for (int i = 0; i < value.size(); ++i) { 473 output.writeSFixed32(fieldNumber, value.get(i)); 474 } 475 } 476 } 477 478 @Override writeSFixed64List(int fieldNumber, List<Long> value, boolean packed)479 public void writeSFixed64List(int fieldNumber, List<Long> value, boolean packed) 480 throws IOException { 481 if (packed) { 482 output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); 483 484 // Compute and write the length of the data. 485 int dataSize = 0; 486 for (int i = 0; i < value.size(); ++i) { 487 dataSize += CodedOutputStream.computeSFixed64SizeNoTag(value.get(i)); 488 } 489 output.writeUInt32NoTag(dataSize); 490 491 // Write the data itself, without any tags. 492 for (int i = 0; i < value.size(); ++i) { 493 output.writeSFixed64NoTag(value.get(i)); 494 } 495 } else { 496 for (int i = 0; i < value.size(); ++i) { 497 output.writeSFixed64(fieldNumber, value.get(i)); 498 } 499 } 500 } 501 502 @Override writeSInt32List(int fieldNumber, List<Integer> value, boolean packed)503 public void writeSInt32List(int fieldNumber, List<Integer> value, boolean packed) 504 throws IOException { 505 if (packed) { 506 output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); 507 508 // Compute and write the length of the data. 509 int dataSize = 0; 510 for (int i = 0; i < value.size(); ++i) { 511 dataSize += CodedOutputStream.computeSInt32SizeNoTag(value.get(i)); 512 } 513 output.writeUInt32NoTag(dataSize); 514 515 // Write the data itself, without any tags. 516 for (int i = 0; i < value.size(); ++i) { 517 output.writeSInt32NoTag(value.get(i)); 518 } 519 } else { 520 for (int i = 0; i < value.size(); ++i) { 521 output.writeSInt32(fieldNumber, value.get(i)); 522 } 523 } 524 } 525 526 @Override writeSInt64List(int fieldNumber, List<Long> value, boolean packed)527 public void writeSInt64List(int fieldNumber, List<Long> value, boolean packed) 528 throws IOException { 529 if (packed) { 530 output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); 531 532 // Compute and write the length of the data. 533 int dataSize = 0; 534 for (int i = 0; i < value.size(); ++i) { 535 dataSize += CodedOutputStream.computeSInt64SizeNoTag(value.get(i)); 536 } 537 output.writeUInt32NoTag(dataSize); 538 539 // Write the data itself, without any tags. 540 for (int i = 0; i < value.size(); ++i) { 541 output.writeSInt64NoTag(value.get(i)); 542 } 543 } else { 544 for (int i = 0; i < value.size(); ++i) { 545 output.writeSInt64(fieldNumber, value.get(i)); 546 } 547 } 548 } 549 550 @Override writeMessageList(int fieldNumber, List<?> value)551 public void writeMessageList(int fieldNumber, List<?> value) throws IOException { 552 for (int i = 0; i < value.size(); ++i) { 553 writeMessage(fieldNumber, value.get(i)); 554 } 555 } 556 557 @Override writeMessageList(int fieldNumber, List<?> value, Schema schema)558 public void writeMessageList(int fieldNumber, List<?> value, Schema schema) throws IOException { 559 for (int i = 0; i < value.size(); ++i) { 560 writeMessage(fieldNumber, value.get(i), schema); 561 } 562 } 563 564 @Override writeGroupList(int fieldNumber, List<?> value)565 public void writeGroupList(int fieldNumber, List<?> value) throws IOException { 566 for (int i = 0; i < value.size(); ++i) { 567 writeGroup(fieldNumber, value.get(i)); 568 } 569 } 570 571 @Override writeGroupList(int fieldNumber, List<?> value, Schema schema)572 public void writeGroupList(int fieldNumber, List<?> value, Schema schema) throws IOException { 573 for (int i = 0; i < value.size(); ++i) { 574 writeGroup(fieldNumber, value.get(i), schema); 575 } 576 } 577 578 @Override writeMap(int fieldNumber, MapEntryLite.Metadata<K, V> metadata, Map<K, V> map)579 public <K, V> void writeMap(int fieldNumber, MapEntryLite.Metadata<K, V> metadata, Map<K, V> map) 580 throws IOException { 581 if (output.isSerializationDeterministic()) { 582 writeDeterministicMap(fieldNumber, metadata, map); 583 return; 584 } 585 for (Map.Entry<K, V> entry : map.entrySet()) { 586 output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); 587 output.writeUInt32NoTag( 588 MapEntryLite.computeSerializedSize(metadata, entry.getKey(), entry.getValue())); 589 MapEntryLite.writeTo(output, metadata, entry.getKey(), entry.getValue()); 590 } 591 } 592 593 @SuppressWarnings("unchecked") writeDeterministicMap( int fieldNumber, MapEntryLite.Metadata<K, V> metadata, Map<K, V> map)594 private <K, V> void writeDeterministicMap( 595 int fieldNumber, MapEntryLite.Metadata<K, V> metadata, Map<K, V> map) throws IOException { 596 switch (metadata.keyType) { 597 case BOOL: 598 V value; 599 if ((value = map.get(Boolean.FALSE)) != null) { 600 writeDeterministicBooleanMapEntry( 601 fieldNumber, /* key= */ false, value, (MapEntryLite.Metadata<Boolean, V>) metadata); 602 } 603 if ((value = map.get(Boolean.TRUE)) != null) { 604 writeDeterministicBooleanMapEntry( 605 fieldNumber, /* key= */ true, value, (MapEntryLite.Metadata<Boolean, V>) metadata); 606 } 607 break; 608 case FIXED32: 609 case INT32: 610 case SFIXED32: 611 case SINT32: 612 case UINT32: 613 writeDeterministicIntegerMap( 614 fieldNumber, (MapEntryLite.Metadata<Integer, V>) metadata, (Map<Integer, V>) map); 615 break; 616 case FIXED64: 617 case INT64: 618 case SFIXED64: 619 case SINT64: 620 case UINT64: 621 writeDeterministicLongMap( 622 fieldNumber, (MapEntryLite.Metadata<Long, V>) metadata, (Map<Long, V>) map); 623 break; 624 case STRING: 625 writeDeterministicStringMap( 626 fieldNumber, (MapEntryLite.Metadata<String, V>) metadata, (Map<String, V>) map); 627 break; 628 default: 629 throw new IllegalArgumentException("does not support key type: " + metadata.keyType); 630 } 631 } 632 writeDeterministicBooleanMapEntry( int fieldNumber, boolean key, V value, MapEntryLite.Metadata<Boolean, V> metadata)633 private <V> void writeDeterministicBooleanMapEntry( 634 int fieldNumber, boolean key, V value, MapEntryLite.Metadata<Boolean, V> metadata) 635 throws IOException { 636 output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); 637 output.writeUInt32NoTag(MapEntryLite.computeSerializedSize(metadata, key, value)); 638 MapEntryLite.writeTo(output, metadata, key, value); 639 } 640 writeDeterministicIntegerMap( int fieldNumber, MapEntryLite.Metadata<Integer, V> metadata, Map<Integer, V> map)641 private <V> void writeDeterministicIntegerMap( 642 int fieldNumber, MapEntryLite.Metadata<Integer, V> metadata, Map<Integer, V> map) 643 throws IOException { 644 int[] keys = new int[map.size()]; 645 int index = 0; 646 for (int k : map.keySet()) { 647 keys[index++] = k; 648 } 649 Arrays.sort(keys); 650 for (int key : keys) { 651 V value = map.get(key); 652 output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); 653 output.writeUInt32NoTag(MapEntryLite.computeSerializedSize(metadata, key, value)); 654 MapEntryLite.writeTo(output, metadata, key, value); 655 } 656 } 657 writeDeterministicLongMap( int fieldNumber, MapEntryLite.Metadata<Long, V> metadata, Map<Long, V> map)658 private <V> void writeDeterministicLongMap( 659 int fieldNumber, MapEntryLite.Metadata<Long, V> metadata, Map<Long, V> map) 660 throws IOException { 661 long[] keys = new long[map.size()]; 662 int index = 0; 663 for (long k : map.keySet()) { 664 keys[index++] = k; 665 } 666 Arrays.sort(keys); 667 for (long key : keys) { 668 V value = map.get(key); 669 output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); 670 output.writeUInt32NoTag(MapEntryLite.computeSerializedSize(metadata, key, value)); 671 MapEntryLite.writeTo(output, metadata, key, value); 672 } 673 } 674 writeDeterministicStringMap( int fieldNumber, MapEntryLite.Metadata<String, V> metadata, Map<String, V> map)675 private <V> void writeDeterministicStringMap( 676 int fieldNumber, MapEntryLite.Metadata<String, V> metadata, Map<String, V> map) 677 throws IOException { 678 String[] keys = new String[map.size()]; 679 int index = 0; 680 for (String k : map.keySet()) { 681 keys[index++] = k; 682 } 683 Arrays.sort(keys); 684 for (String key : keys) { 685 V value = map.get(key); 686 output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); 687 output.writeUInt32NoTag(MapEntryLite.computeSerializedSize(metadata, key, value)); 688 MapEntryLite.writeTo(output, metadata, key, value); 689 } 690 } 691 } 692