1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.util.proto; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.util.Log; 22 23 import java.io.FileDescriptor; 24 import java.io.FileOutputStream; 25 import java.io.IOException; 26 import java.io.OutputStream; 27 import java.io.UnsupportedEncodingException; 28 29 /** 30 * Class to write to a protobuf stream. 31 * 32 * <p> 33 * This API is not as convenient or type safe as the standard protobuf 34 * classes. If possible, the best recommended library is to use protobuf lite. 35 * However, in environments (such as the Android platform itself), a 36 * more memory efficient version is necessary. 37 * 38 * <p>Each write method takes an ID code from the protoc generated classes 39 * and the value to write. To make a nested object, call {@link #start(long)} 40 * and then {@link #end(long)} when you are done. 41 * 42 * <p>The ID codes have type information embedded into them, so if you call 43 * the incorrect function you will get an {@link IllegalArgumentException}. 44 * 45 * <p>To retrieve the encoded protobuf stream, call {@link #getBytes()}. 46 * 47 * stream as the top-level objects are finished. 48 * 49 */ 50 51 /* IMPLEMENTATION NOTES 52 * 53 * Because protobuf has inner values, and they are length prefixed, and 54 * those sizes themselves are stored with a variable length encoding, it 55 * is impossible to know how big an object will be in a single pass. 56 * 57 * The traditional way is to copy the in-memory representation of an object 58 * into the generated proto Message objects, do a traversal of those to 59 * cache the size, and then write the size-prefixed buffers. 60 * 61 * We are trying to avoid too much generated code here, but this class still 62 * needs to have API. We can't have the multiple passes be done by the 63 * calling code. In addition, we want to avoid the memory high water mark 64 * of duplicating all of the values into the traditional in-memory Message 65 * objects. We need to find another way. 66 * 67 * So what we do here is to let the calling code write the data into a 68 * byte[] (actually a collection of them wrapped in the EncodedBuffer class), 69 * but not do the varint encoding of the sub-message sizes. Then, we do a 70 * recursive traversal of the buffer itself, calculating the sizes (which are 71 * then knowable, although still not the actual sizes in the buffer because of 72 * possible further nesting). Then we do a third pass, compacting the 73 * buffer and varint encoding the sizes. 74 * 75 * This gets us a relatively small number of fixed-size allocations, 76 * which is less likely to cause memory fragmentation or churn the GC, and 77 * the same number of data copies as we would have gotten with setting it 78 * field-by-field in generated code, and no code bloat from generated code. 79 * The final data copy is also done with System.arraycopy, which will be 80 * more efficient, in general, than doing the individual fields twice (as in 81 * the traditional way). 82 * 83 * To accomplish the multiple passes, whenever we write a 84 * WIRE_TYPE_LENGTH_DELIMITED field, we write the size occupied in our 85 * buffer as a fixed 32 bit int (called childRawSize), not a variable length 86 * one. We reserve another 32 bit slot for the computed size (called 87 * childEncodedSize). If we know the size up front, as we do for strings 88 * and byte[], then we also put that into childEncodedSize, if we don't, we 89 * write the negative of childRawSize, as a sentinel that we need to 90 * compute it during the second pass and recursively compact it during the 91 * third pass. 92 * 93 * Unsigned size varints can be up to five bytes long, but we reserve eight 94 * bytes for overhead, so we know that when we compact the buffer, there 95 * will always be space for the encoded varint. 96 * 97 * When we can figure out the size ahead of time, we do, in order 98 * to save overhead with recalculating it, and with the later arraycopy. 99 * 100 * During the period between when the caller has called #start, but 101 * not yet called #end, we maintain a linked list of the tokens 102 * returned by #start, stored in those 8 bytes of size storage space. 103 * We use that linked list of tokens to ensure that the caller has 104 * correctly matched pairs of #start and #end calls, and issue 105 * errors if they are not matched. 106 */ 107 @android.ravenwood.annotation.RavenwoodKeepWholeClass 108 public final class ProtoOutputStream extends ProtoStream { 109 /** 110 * @hide 111 */ 112 public static final String TAG = "ProtoOutputStream"; 113 114 /** 115 * Our buffer. 116 */ 117 private EncodedBuffer mBuffer; 118 119 /** 120 * Our stream. If there is one. 121 */ 122 private OutputStream mStream; 123 124 /** 125 * Current nesting depth of startObject calls. 126 */ 127 private int mDepth; 128 129 /** 130 * An ID given to objects and returned in the token from startObject 131 * and stored in the buffer until endObject is called, where the two 132 * are checked. 133 * 134 * <p>Starts at -1 and becomes more negative, so the values 135 * aren't likely to alias with the size it will be overwritten with, 136 * which tend to be small, and we will be more likely to catch when 137 * the caller of endObject uses a stale token that they didn't intend 138 * to (e.g. copy and paste error). 139 */ 140 private int mNextObjectId = -1; 141 142 /** 143 * The object token we are expecting in endObject. 144 * 145 * <p>If another call to startObject happens, this is written to that location, which gives 146 * us a stack, stored in the space for the as-yet unused size fields. 147 */ 148 private long mExpectedObjectToken; 149 150 /** 151 * Index in mBuffer that we should start copying from on the next 152 * pass of compaction. 153 */ 154 private int mCopyBegin; 155 156 /** 157 * Whether we've already compacted 158 */ 159 private boolean mCompacted; 160 161 /** 162 * Construct a {@link ProtoOutputStream} with the default chunk size. 163 * 164 * <p>This is for an in-memory proto. The caller should use {@link #getBytes()} for the result. 165 */ ProtoOutputStream()166 public ProtoOutputStream() { 167 this(0); 168 } 169 170 /** 171 * Construct a {@link ProtoOutputStream with the given chunk size. 172 * 173 * <p>This is for an in-memory proto. The caller should use {@link #getBytes()} for the result. 174 */ ProtoOutputStream(int chunkSize)175 public ProtoOutputStream(int chunkSize) { 176 mBuffer = new EncodedBuffer(chunkSize); 177 } 178 179 /** 180 * Construct a {@link ProtoOutputStream} that sits on top of an {@link OutputStream}. 181 * 182 * <p>The {@link #flush()} method must be called when done writing 183 * to flush any remaining data, although data *may* be written at intermediate 184 * points within the writing as well. 185 */ ProtoOutputStream(@onNull OutputStream stream)186 public ProtoOutputStream(@NonNull OutputStream stream) { 187 this(); 188 mStream = stream; 189 } 190 191 /** 192 * Construct a {@link ProtoOutputStream} that sits on top of a {@link FileDescriptor}. 193 * 194 * <p>The {@link #flush()} method must be called when done writing 195 * to flush any remaining data, although data *may* be written at intermediate 196 * points within the writing as well. 197 * 198 * @hide 199 */ ProtoOutputStream(@onNull FileDescriptor fd)200 public ProtoOutputStream(@NonNull FileDescriptor fd) { 201 this(new FileOutputStream(fd)); 202 } 203 204 /** 205 * Returns the total size of the data that has been written, after full 206 * protobuf encoding has occurred. 207 * 208 * @return the uncompressed buffer size 209 */ getRawSize()210 public int getRawSize() { 211 if (mCompacted) { 212 return getBytes().length; 213 } else { 214 return mBuffer.getSize(); 215 } 216 } 217 218 /** 219 * Write a value for the given fieldId. 220 * 221 * <p>Will automatically convert for the following field types, and 222 * throw an exception for others: double, float, int32, int64, uint32, uint64, 223 * sint32, sint64, fixed32, fixed64, sfixed32, sfixed64, bool, enum. 224 * 225 * @param fieldId The field identifier constant from the generated class. 226 * @param val The value. 227 */ write(long fieldId, double val)228 public void write(long fieldId, double val) { 229 assertNotCompacted(); 230 final int id = (int)fieldId; 231 232 switch ((int)((fieldId & (FIELD_TYPE_MASK | FIELD_COUNT_MASK)) >> FIELD_TYPE_SHIFT)) { 233 // double 234 case (int)((FIELD_TYPE_DOUBLE | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 235 writeDoubleImpl(id, (double)val); 236 break; 237 case (int)((FIELD_TYPE_DOUBLE | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 238 case (int)((FIELD_TYPE_DOUBLE | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 239 writeRepeatedDoubleImpl(id, (double)val); 240 break; 241 // float 242 case (int)((FIELD_TYPE_FLOAT | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 243 writeFloatImpl(id, (float)val); 244 break; 245 case (int)((FIELD_TYPE_FLOAT | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 246 case (int)((FIELD_TYPE_FLOAT | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 247 writeRepeatedFloatImpl(id, (float)val); 248 break; 249 // int32 250 case (int)((FIELD_TYPE_INT32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 251 writeInt32Impl(id, (int)val); 252 break; 253 case (int)((FIELD_TYPE_INT32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 254 case (int)((FIELD_TYPE_INT32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 255 writeRepeatedInt32Impl(id, (int)val); 256 break; 257 // int64 258 case (int)((FIELD_TYPE_INT64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 259 writeInt64Impl(id, (long)val); 260 break; 261 case (int)((FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 262 case (int)((FIELD_TYPE_INT64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 263 writeRepeatedInt64Impl(id, (long)val); 264 break; 265 // uint32 266 case (int)((FIELD_TYPE_UINT32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 267 writeUInt32Impl(id, (int)val); 268 break; 269 case (int)((FIELD_TYPE_UINT32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 270 case (int)((FIELD_TYPE_UINT32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 271 writeRepeatedUInt32Impl(id, (int)val); 272 break; 273 // uint64 274 case (int)((FIELD_TYPE_UINT64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 275 writeUInt64Impl(id, (long)val); 276 break; 277 case (int)((FIELD_TYPE_UINT64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 278 case (int)((FIELD_TYPE_UINT64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 279 writeRepeatedUInt64Impl(id, (long)val); 280 break; 281 // sint32 282 case (int)((FIELD_TYPE_SINT32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 283 writeSInt32Impl(id, (int)val); 284 break; 285 case (int)((FIELD_TYPE_SINT32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 286 case (int)((FIELD_TYPE_SINT32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 287 writeRepeatedSInt32Impl(id, (int)val); 288 break; 289 // sint64 290 case (int)((FIELD_TYPE_SINT64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 291 writeSInt64Impl(id, (long)val); 292 break; 293 case (int)((FIELD_TYPE_SINT64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 294 case (int)((FIELD_TYPE_SINT64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 295 writeRepeatedSInt64Impl(id, (long)val); 296 break; 297 // fixed32 298 case (int)((FIELD_TYPE_FIXED32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 299 writeFixed32Impl(id, (int)val); 300 break; 301 case (int)((FIELD_TYPE_FIXED32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 302 case (int)((FIELD_TYPE_FIXED32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 303 writeRepeatedFixed32Impl(id, (int)val); 304 break; 305 // fixed64 306 case (int)((FIELD_TYPE_FIXED64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 307 writeFixed64Impl(id, (long)val); 308 break; 309 case (int)((FIELD_TYPE_FIXED64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 310 case (int)((FIELD_TYPE_FIXED64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 311 writeRepeatedFixed64Impl(id, (long)val); 312 break; 313 // sfixed32 314 case (int)((FIELD_TYPE_SFIXED32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 315 writeSFixed32Impl(id, (int)val); 316 break; 317 case (int)((FIELD_TYPE_SFIXED32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 318 case (int)((FIELD_TYPE_SFIXED32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 319 writeRepeatedSFixed32Impl(id, (int)val); 320 break; 321 // sfixed64 322 case (int)((FIELD_TYPE_SFIXED64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 323 writeSFixed64Impl(id, (long)val); 324 break; 325 case (int)((FIELD_TYPE_SFIXED64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 326 case (int)((FIELD_TYPE_SFIXED64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 327 writeRepeatedSFixed64Impl(id, (long)val); 328 break; 329 // bool 330 case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 331 writeBoolImpl(id, val != 0); 332 break; 333 case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 334 case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 335 writeRepeatedBoolImpl(id, val != 0); 336 break; 337 // enum 338 case (int)((FIELD_TYPE_ENUM | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 339 writeEnumImpl(id, (int)val); 340 break; 341 case (int)((FIELD_TYPE_ENUM | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 342 case (int)((FIELD_TYPE_ENUM | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 343 writeRepeatedEnumImpl(id, (int)val); 344 break; 345 // string, bytes, object not allowed here. 346 default: { 347 throw new IllegalArgumentException("Attempt to call write(long, double) with " 348 + getFieldIdString(fieldId)); 349 } 350 } 351 } 352 353 /** 354 * Write a value for the given fieldId. 355 * 356 * <p>Will automatically convert for the following field types, and 357 * throw an exception for others: double, float, int32, int64, uint32, uint64, 358 * sint32, sint64, fixed32, fixed64, sfixed32, sfixed64, bool, enum. 359 * 360 * @param fieldId The field identifier constant from the generated class. 361 * @param val The value. 362 */ write(long fieldId, float val)363 public void write(long fieldId, float val) { 364 assertNotCompacted(); 365 final int id = (int)fieldId; 366 367 switch ((int)((fieldId & (FIELD_TYPE_MASK | FIELD_COUNT_MASK)) >> FIELD_TYPE_SHIFT)) { 368 // double 369 case (int)((FIELD_TYPE_DOUBLE | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 370 writeDoubleImpl(id, (double)val); 371 break; 372 case (int)((FIELD_TYPE_DOUBLE | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 373 case (int)((FIELD_TYPE_DOUBLE | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 374 writeRepeatedDoubleImpl(id, (double)val); 375 break; 376 // float 377 case (int)((FIELD_TYPE_FLOAT | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 378 writeFloatImpl(id, (float)val); 379 break; 380 case (int)((FIELD_TYPE_FLOAT | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 381 case (int)((FIELD_TYPE_FLOAT | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 382 writeRepeatedFloatImpl(id, (float)val); 383 break; 384 // int32 385 case (int)((FIELD_TYPE_INT32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 386 writeInt32Impl(id, (int)val); 387 break; 388 case (int)((FIELD_TYPE_INT32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 389 case (int)((FIELD_TYPE_INT32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 390 writeRepeatedInt32Impl(id, (int)val); 391 break; 392 // int64 393 case (int)((FIELD_TYPE_INT64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 394 writeInt64Impl(id, (long)val); 395 break; 396 case (int)((FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 397 case (int)((FIELD_TYPE_INT64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 398 writeRepeatedInt64Impl(id, (long)val); 399 break; 400 // uint32 401 case (int)((FIELD_TYPE_UINT32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 402 writeUInt32Impl(id, (int)val); 403 break; 404 case (int)((FIELD_TYPE_UINT32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 405 case (int)((FIELD_TYPE_UINT32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 406 writeRepeatedUInt32Impl(id, (int)val); 407 break; 408 // uint64 409 case (int)((FIELD_TYPE_UINT64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 410 writeUInt64Impl(id, (long)val); 411 break; 412 case (int)((FIELD_TYPE_UINT64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 413 case (int)((FIELD_TYPE_UINT64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 414 writeRepeatedUInt64Impl(id, (long)val); 415 break; 416 // sint32 417 case (int)((FIELD_TYPE_SINT32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 418 writeSInt32Impl(id, (int)val); 419 break; 420 case (int)((FIELD_TYPE_SINT32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 421 case (int)((FIELD_TYPE_SINT32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 422 writeRepeatedSInt32Impl(id, (int)val); 423 break; 424 // sint64 425 case (int)((FIELD_TYPE_SINT64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 426 writeSInt64Impl(id, (long)val); 427 break; 428 case (int)((FIELD_TYPE_SINT64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 429 case (int)((FIELD_TYPE_SINT64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 430 writeRepeatedSInt64Impl(id, (long)val); 431 break; 432 // fixed32 433 case (int)((FIELD_TYPE_FIXED32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 434 writeFixed32Impl(id, (int)val); 435 break; 436 case (int)((FIELD_TYPE_FIXED32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 437 case (int)((FIELD_TYPE_FIXED32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 438 writeRepeatedFixed32Impl(id, (int)val); 439 break; 440 // fixed64 441 case (int)((FIELD_TYPE_FIXED64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 442 writeFixed64Impl(id, (long)val); 443 break; 444 case (int)((FIELD_TYPE_FIXED64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 445 case (int)((FIELD_TYPE_FIXED64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 446 writeRepeatedFixed64Impl(id, (long)val); 447 break; 448 // sfixed32 449 case (int)((FIELD_TYPE_SFIXED32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 450 writeSFixed32Impl(id, (int)val); 451 break; 452 case (int)((FIELD_TYPE_SFIXED32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 453 case (int)((FIELD_TYPE_SFIXED32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 454 writeRepeatedSFixed32Impl(id, (int)val); 455 break; 456 // sfixed64 457 case (int)((FIELD_TYPE_SFIXED64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 458 writeSFixed64Impl(id, (long)val); 459 break; 460 case (int)((FIELD_TYPE_SFIXED64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 461 case (int)((FIELD_TYPE_SFIXED64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 462 writeRepeatedSFixed64Impl(id, (long)val); 463 break; 464 // bool 465 case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 466 writeBoolImpl(id, val != 0); 467 break; 468 case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 469 case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 470 writeRepeatedBoolImpl(id, val != 0); 471 break; 472 // enum 473 case (int)((FIELD_TYPE_ENUM | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 474 writeEnumImpl(id, (int)val); 475 break; 476 case (int)((FIELD_TYPE_ENUM | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 477 case (int)((FIELD_TYPE_ENUM | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 478 writeRepeatedEnumImpl(id, (int)val); 479 break; 480 // string, bytes, object not allowed here. 481 default: { 482 throw new IllegalArgumentException("Attempt to call write(long, float) with " 483 + getFieldIdString(fieldId)); 484 } 485 } 486 } 487 488 /** 489 * Write a value for the given fieldId. 490 * 491 * <p>Will automatically convert for the following field types, and 492 * throw an exception for others: double, float, int32, int64, uint32, uint64, 493 * sint32, sint64, fixed32, fixed64, sfixed32, sfixed64, bool, enum. 494 * 495 * @param fieldId The field identifier constant from the generated class. 496 * @param val The value. 497 */ write(long fieldId, int val)498 public void write(long fieldId, int val) { 499 assertNotCompacted(); 500 final int id = (int)fieldId; 501 502 switch ((int)((fieldId & (FIELD_TYPE_MASK | FIELD_COUNT_MASK)) >> FIELD_TYPE_SHIFT)) { 503 // double 504 case (int)((FIELD_TYPE_DOUBLE | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 505 writeDoubleImpl(id, (double)val); 506 break; 507 case (int)((FIELD_TYPE_DOUBLE | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 508 case (int)((FIELD_TYPE_DOUBLE | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 509 writeRepeatedDoubleImpl(id, (double)val); 510 break; 511 // float 512 case (int)((FIELD_TYPE_FLOAT | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 513 writeFloatImpl(id, (float)val); 514 break; 515 case (int)((FIELD_TYPE_FLOAT | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 516 case (int)((FIELD_TYPE_FLOAT | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 517 writeRepeatedFloatImpl(id, (float)val); 518 break; 519 // int32 520 case (int)((FIELD_TYPE_INT32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 521 writeInt32Impl(id, (int)val); 522 break; 523 case (int)((FIELD_TYPE_INT32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 524 case (int)((FIELD_TYPE_INT32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 525 writeRepeatedInt32Impl(id, (int)val); 526 break; 527 // int64 528 case (int)((FIELD_TYPE_INT64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 529 writeInt64Impl(id, (long)val); 530 break; 531 case (int)((FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 532 case (int)((FIELD_TYPE_INT64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 533 writeRepeatedInt64Impl(id, (long)val); 534 break; 535 // uint32 536 case (int)((FIELD_TYPE_UINT32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 537 writeUInt32Impl(id, (int)val); 538 break; 539 case (int)((FIELD_TYPE_UINT32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 540 case (int)((FIELD_TYPE_UINT32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 541 writeRepeatedUInt32Impl(id, (int)val); 542 break; 543 // uint64 544 case (int)((FIELD_TYPE_UINT64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 545 writeUInt64Impl(id, (long)val); 546 break; 547 case (int)((FIELD_TYPE_UINT64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 548 case (int)((FIELD_TYPE_UINT64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 549 writeRepeatedUInt64Impl(id, (long)val); 550 break; 551 // sint32 552 case (int)((FIELD_TYPE_SINT32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 553 writeSInt32Impl(id, (int)val); 554 break; 555 case (int)((FIELD_TYPE_SINT32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 556 case (int)((FIELD_TYPE_SINT32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 557 writeRepeatedSInt32Impl(id, (int)val); 558 break; 559 // sint64 560 case (int)((FIELD_TYPE_SINT64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 561 writeSInt64Impl(id, (long)val); 562 break; 563 case (int)((FIELD_TYPE_SINT64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 564 case (int)((FIELD_TYPE_SINT64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 565 writeRepeatedSInt64Impl(id, (long)val); 566 break; 567 // fixed32 568 case (int)((FIELD_TYPE_FIXED32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 569 writeFixed32Impl(id, (int)val); 570 break; 571 case (int)((FIELD_TYPE_FIXED32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 572 case (int)((FIELD_TYPE_FIXED32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 573 writeRepeatedFixed32Impl(id, (int)val); 574 break; 575 // fixed64 576 case (int)((FIELD_TYPE_FIXED64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 577 writeFixed64Impl(id, (long)val); 578 break; 579 case (int)((FIELD_TYPE_FIXED64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 580 case (int)((FIELD_TYPE_FIXED64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 581 writeRepeatedFixed64Impl(id, (long)val); 582 break; 583 // sfixed32 584 case (int)((FIELD_TYPE_SFIXED32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 585 writeSFixed32Impl(id, (int)val); 586 break; 587 case (int)((FIELD_TYPE_SFIXED32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 588 case (int)((FIELD_TYPE_SFIXED32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 589 writeRepeatedSFixed32Impl(id, (int)val); 590 break; 591 // sfixed64 592 case (int)((FIELD_TYPE_SFIXED64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 593 writeSFixed64Impl(id, (long)val); 594 break; 595 case (int)((FIELD_TYPE_SFIXED64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 596 case (int)((FIELD_TYPE_SFIXED64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 597 writeRepeatedSFixed64Impl(id, (long)val); 598 break; 599 // bool 600 case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 601 writeBoolImpl(id, val != 0); 602 break; 603 case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 604 case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 605 writeRepeatedBoolImpl(id, val != 0); 606 break; 607 // enum 608 case (int)((FIELD_TYPE_ENUM | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 609 writeEnumImpl(id, (int)val); 610 break; 611 case (int)((FIELD_TYPE_ENUM | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 612 case (int)((FIELD_TYPE_ENUM | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 613 writeRepeatedEnumImpl(id, (int)val); 614 break; 615 // string, bytes, object not allowed here. 616 default: { 617 throw new IllegalArgumentException("Attempt to call write(long, int) with " 618 + getFieldIdString(fieldId)); 619 } 620 } 621 } 622 623 /** 624 * Write a value for the given fieldId. 625 * 626 * <p>Will automatically convert for the following field types, and 627 * throw an exception for others: double, float, int32, int64, uint32, uint64, 628 * sint32, sint64, fixed32, fixed64, sfixed32, sfixed64, bool, enum. 629 * 630 * @param fieldId The field identifier constant from the generated class. 631 * @param val The value. 632 */ write(long fieldId, long val)633 public void write(long fieldId, long val) { 634 assertNotCompacted(); 635 final int id = (int)fieldId; 636 637 switch ((int)((fieldId & (FIELD_TYPE_MASK | FIELD_COUNT_MASK)) >> FIELD_TYPE_SHIFT)) { 638 // double 639 case (int)((FIELD_TYPE_DOUBLE | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 640 writeDoubleImpl(id, (double)val); 641 break; 642 case (int)((FIELD_TYPE_DOUBLE | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 643 case (int)((FIELD_TYPE_DOUBLE | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 644 writeRepeatedDoubleImpl(id, (double)val); 645 break; 646 // float 647 case (int)((FIELD_TYPE_FLOAT | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 648 writeFloatImpl(id, (float)val); 649 break; 650 case (int)((FIELD_TYPE_FLOAT | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 651 case (int)((FIELD_TYPE_FLOAT | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 652 writeRepeatedFloatImpl(id, (float)val); 653 break; 654 // int32 655 case (int)((FIELD_TYPE_INT32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 656 writeInt32Impl(id, (int)val); 657 break; 658 case (int)((FIELD_TYPE_INT32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 659 case (int)((FIELD_TYPE_INT32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 660 writeRepeatedInt32Impl(id, (int)val); 661 break; 662 // int64 663 case (int)((FIELD_TYPE_INT64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 664 writeInt64Impl(id, (long)val); 665 break; 666 case (int)((FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 667 case (int)((FIELD_TYPE_INT64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 668 writeRepeatedInt64Impl(id, (long)val); 669 break; 670 // uint32 671 case (int)((FIELD_TYPE_UINT32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 672 writeUInt32Impl(id, (int)val); 673 break; 674 case (int)((FIELD_TYPE_UINT32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 675 case (int)((FIELD_TYPE_UINT32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 676 writeRepeatedUInt32Impl(id, (int)val); 677 break; 678 // uint64 679 case (int)((FIELD_TYPE_UINT64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 680 writeUInt64Impl(id, (long)val); 681 break; 682 case (int)((FIELD_TYPE_UINT64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 683 case (int)((FIELD_TYPE_UINT64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 684 writeRepeatedUInt64Impl(id, (long)val); 685 break; 686 // sint32 687 case (int)((FIELD_TYPE_SINT32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 688 writeSInt32Impl(id, (int)val); 689 break; 690 case (int)((FIELD_TYPE_SINT32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 691 case (int)((FIELD_TYPE_SINT32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 692 writeRepeatedSInt32Impl(id, (int)val); 693 break; 694 // sint64 695 case (int)((FIELD_TYPE_SINT64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 696 writeSInt64Impl(id, (long)val); 697 break; 698 case (int)((FIELD_TYPE_SINT64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 699 case (int)((FIELD_TYPE_SINT64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 700 writeRepeatedSInt64Impl(id, (long)val); 701 break; 702 // fixed32 703 case (int)((FIELD_TYPE_FIXED32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 704 writeFixed32Impl(id, (int)val); 705 break; 706 case (int)((FIELD_TYPE_FIXED32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 707 case (int)((FIELD_TYPE_FIXED32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 708 writeRepeatedFixed32Impl(id, (int)val); 709 break; 710 // fixed64 711 case (int)((FIELD_TYPE_FIXED64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 712 writeFixed64Impl(id, (long)val); 713 break; 714 case (int)((FIELD_TYPE_FIXED64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 715 case (int)((FIELD_TYPE_FIXED64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 716 writeRepeatedFixed64Impl(id, (long)val); 717 break; 718 // sfixed32 719 case (int)((FIELD_TYPE_SFIXED32 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 720 writeSFixed32Impl(id, (int)val); 721 break; 722 case (int)((FIELD_TYPE_SFIXED32 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 723 case (int)((FIELD_TYPE_SFIXED32 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 724 writeRepeatedSFixed32Impl(id, (int)val); 725 break; 726 // sfixed64 727 case (int)((FIELD_TYPE_SFIXED64 | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 728 writeSFixed64Impl(id, (long)val); 729 break; 730 case (int)((FIELD_TYPE_SFIXED64 | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 731 case (int)((FIELD_TYPE_SFIXED64 | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 732 writeRepeatedSFixed64Impl(id, (long)val); 733 break; 734 // bool 735 case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 736 writeBoolImpl(id, val != 0); 737 break; 738 case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 739 case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 740 writeRepeatedBoolImpl(id, val != 0); 741 break; 742 // enum 743 case (int)((FIELD_TYPE_ENUM | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 744 writeEnumImpl(id, (int)val); 745 break; 746 case (int)((FIELD_TYPE_ENUM | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 747 case (int)((FIELD_TYPE_ENUM | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 748 writeRepeatedEnumImpl(id, (int)val); 749 break; 750 // string, bytes, object not allowed here. 751 default: { 752 throw new IllegalArgumentException("Attempt to call write(long, long) with " 753 + getFieldIdString(fieldId)); 754 } 755 } 756 } 757 758 /** 759 * Write a boolean value for the given fieldId. 760 * 761 * <p>If the field is not a bool field, an {@link IllegalStateException} will be thrown. 762 * 763 * @param fieldId The field identifier constant from the generated class. 764 * @param val The value. 765 */ write(long fieldId, boolean val)766 public void write(long fieldId, boolean val) { 767 assertNotCompacted(); 768 final int id = (int)fieldId; 769 770 switch ((int)((fieldId & (FIELD_TYPE_MASK | FIELD_COUNT_MASK)) >> FIELD_TYPE_SHIFT)) { 771 // bool 772 case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 773 writeBoolImpl(id, val); 774 break; 775 case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 776 case (int)((FIELD_TYPE_BOOL | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 777 writeRepeatedBoolImpl(id, val); 778 break; 779 // nothing else allowed 780 default: { 781 throw new IllegalArgumentException("Attempt to call write(long, boolean) with " 782 + getFieldIdString(fieldId)); 783 } 784 } 785 } 786 787 /** 788 * Write a string value for the given fieldId. 789 * 790 * <p>If the field is not a string field, an exception will be thrown. 791 * 792 * @param fieldId The field identifier constant from the generated class. 793 * @param val The value. 794 */ write(long fieldId, @Nullable String val)795 public void write(long fieldId, @Nullable String val) { 796 assertNotCompacted(); 797 final int id = (int)fieldId; 798 799 switch ((int)((fieldId & (FIELD_TYPE_MASK | FIELD_COUNT_MASK)) >> FIELD_TYPE_SHIFT)) { 800 // string 801 case (int)((FIELD_TYPE_STRING | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 802 writeStringImpl(id, val); 803 break; 804 case (int)((FIELD_TYPE_STRING | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 805 case (int)((FIELD_TYPE_STRING | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 806 writeRepeatedStringImpl(id, val); 807 break; 808 // nothing else allowed 809 default: { 810 throw new IllegalArgumentException("Attempt to call write(long, String) with " 811 + getFieldIdString(fieldId)); 812 } 813 } 814 } 815 816 /** 817 * Write a byte[] value for the given fieldId. 818 * 819 * <p>If the field is not a bytes or object field, an exception will be thrown. 820 * 821 * @param fieldId The field identifier constant from the generated class. 822 * @param val The value. 823 */ write(long fieldId, @Nullable byte[] val)824 public void write(long fieldId, @Nullable byte[] val) { 825 assertNotCompacted(); 826 final int id = (int)fieldId; 827 828 switch ((int) ((fieldId & (FIELD_TYPE_MASK | FIELD_COUNT_MASK)) >> FIELD_TYPE_SHIFT)) { 829 // bytes 830 case (int) ((FIELD_TYPE_BYTES | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 831 writeBytesImpl(id, val); 832 break; 833 case (int) ((FIELD_TYPE_BYTES | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 834 case (int) ((FIELD_TYPE_BYTES | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 835 writeRepeatedBytesImpl(id, val); 836 break; 837 // Object 838 case (int) ((FIELD_TYPE_MESSAGE | FIELD_COUNT_SINGLE) >> FIELD_TYPE_SHIFT): 839 writeObjectImpl(id, val); 840 break; 841 case (int) ((FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED) >> FIELD_TYPE_SHIFT): 842 case (int) ((FIELD_TYPE_MESSAGE | FIELD_COUNT_PACKED) >> FIELD_TYPE_SHIFT): 843 writeRepeatedObjectImpl(id, val); 844 break; 845 // nothing else allowed 846 default: { 847 throw new IllegalArgumentException("Attempt to call write(long, byte[]) with " 848 + getFieldIdString(fieldId)); 849 } 850 } 851 } 852 853 /** 854 * Start a sub object. 855 * 856 * @param fieldId The field identifier constant from the generated class. 857 * @return The token to call {@link #end(long)} with. 858 */ start(long fieldId)859 public long start(long fieldId) { 860 assertNotCompacted(); 861 final int id = (int)fieldId; 862 863 if ((fieldId & FIELD_TYPE_MASK) == FIELD_TYPE_MESSAGE) { 864 final long count = fieldId & FIELD_COUNT_MASK; 865 if (count == FIELD_COUNT_SINGLE) { 866 return startObjectImpl(id, false); 867 } else if (count == FIELD_COUNT_REPEATED || count == FIELD_COUNT_PACKED) { 868 return startObjectImpl(id, true); 869 } 870 } 871 throw new IllegalArgumentException("Attempt to call start(long) with " 872 + getFieldIdString(fieldId)); 873 } 874 875 /** 876 * End the object started by start() that returned token. 877 * 878 * @param token The token returned from {@link #start(long)} 879 */ end(long token)880 public void end(long token) { 881 endObjectImpl(token, getRepeatedFromToken(token)); 882 } 883 884 // 885 // proto3 type: double 886 // java type: double 887 // encoding: fixed64 888 // wire type: WIRE_TYPE_FIXED64 889 // 890 891 /** 892 * Write a single proto "double" type field value. 893 * 894 * @deprecated Use {@link #write(long, double)} instead. 895 * @hide 896 */ 897 @Deprecated writeDouble(long fieldId, double val)898 public void writeDouble(long fieldId, double val) { 899 assertNotCompacted(); 900 final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_DOUBLE); 901 902 writeDoubleImpl(id, val); 903 } 904 writeDoubleImpl(int id, double val)905 private void writeDoubleImpl(int id, double val) { 906 if (val != 0) { 907 writeTag(id, WIRE_TYPE_FIXED64); 908 mBuffer.writeRawFixed64(Double.doubleToLongBits(val)); 909 } 910 } 911 912 /** 913 * Write a single repeated proto "double" type field value. 914 * 915 * @deprecated Use {@link #write(long, double)} instead. 916 * @hide 917 */ 918 @Deprecated writeRepeatedDouble(long fieldId, double val)919 public void writeRepeatedDouble(long fieldId, double val) { 920 assertNotCompacted(); 921 final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_DOUBLE); 922 923 writeRepeatedDoubleImpl(id, val); 924 } 925 writeRepeatedDoubleImpl(int id, double val)926 private void writeRepeatedDoubleImpl(int id, double val) { 927 writeTag(id, WIRE_TYPE_FIXED64); 928 mBuffer.writeRawFixed64(Double.doubleToLongBits(val)); 929 } 930 931 /** 932 * Write a list of packed proto "double" type field values. 933 * 934 * @deprecated Use {@link #write(long, double)} instead. 935 * @hide 936 */ 937 @Deprecated writePackedDouble(long fieldId, @Nullable double[] val)938 public void writePackedDouble(long fieldId, @Nullable double[] val) { 939 assertNotCompacted(); 940 final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_DOUBLE); 941 942 final int N = val != null ? val.length : 0; 943 if (N > 0) { 944 writeKnownLengthHeader(id, N * 8); 945 for (int i=0; i<N; i++) { 946 mBuffer.writeRawFixed64(Double.doubleToLongBits(val[i])); 947 } 948 } 949 } 950 951 // 952 // proto3 type: float 953 // java type: float 954 // encoding: fixed32 955 // wire type: WIRE_TYPE_FIXED32 956 // 957 958 /** 959 * Write a single proto "float" type field value. 960 * 961 * @deprecated Use {@link #write(long, float)} instead. 962 * @hide 963 */ 964 @Deprecated writeFloat(long fieldId, float val)965 public void writeFloat(long fieldId, float val) { 966 assertNotCompacted(); 967 final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_FLOAT); 968 969 writeFloatImpl(id, val); 970 } 971 writeFloatImpl(int id, float val)972 private void writeFloatImpl(int id, float val) { 973 if (val != 0) { 974 writeTag(id, WIRE_TYPE_FIXED32); 975 mBuffer.writeRawFixed32(Float.floatToIntBits(val)); 976 } 977 } 978 979 /** 980 * Write a single repeated proto "float" type field value. 981 * 982 * @deprecated Use {@link #write(long, float)} instead. 983 * @hide 984 */ 985 @Deprecated writeRepeatedFloat(long fieldId, float val)986 public void writeRepeatedFloat(long fieldId, float val) { 987 assertNotCompacted(); 988 final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_FLOAT); 989 990 writeRepeatedFloatImpl(id, val); 991 } 992 writeRepeatedFloatImpl(int id, float val)993 private void writeRepeatedFloatImpl(int id, float val) { 994 writeTag(id, WIRE_TYPE_FIXED32); 995 mBuffer.writeRawFixed32(Float.floatToIntBits(val)); 996 } 997 998 /** 999 * Write a list of packed proto "float" type field value. 1000 * 1001 * @deprecated Use {@link #write(long, float)} instead. 1002 * @hide 1003 */ 1004 @Deprecated writePackedFloat(long fieldId, @Nullable float[] val)1005 public void writePackedFloat(long fieldId, @Nullable float[] val) { 1006 assertNotCompacted(); 1007 final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_FLOAT); 1008 1009 final int N = val != null ? val.length : 0; 1010 if (N > 0) { 1011 writeKnownLengthHeader(id, N * 4); 1012 for (int i=0; i<N; i++) { 1013 mBuffer.writeRawFixed32(Float.floatToIntBits(val[i])); 1014 } 1015 } 1016 } 1017 1018 // 1019 // proto3 type: int32 1020 // java type: int 1021 // signed/unsigned: signed 1022 // encoding: varint 1023 // wire type: WIRE_TYPE_VARINT 1024 // 1025 1026 /** 1027 * Writes a java int as an usigned varint. 1028 * 1029 * <p>The unadorned int32 type in protobuf is unfortunate because it 1030 * is stored in memory as a signed value, but encodes as unsigned 1031 * varints, which are formally always longs. So here, we encode 1032 * negative values as 64 bits, which will get the sign-extension, 1033 * and positive values as 32 bits, which saves a marginal amount 1034 * of work in that it processes ints instead of longs. 1035 */ writeUnsignedVarintFromSignedInt(int val)1036 private void writeUnsignedVarintFromSignedInt(int val) { 1037 if (val >= 0) { 1038 mBuffer.writeRawVarint32(val); 1039 } else { 1040 mBuffer.writeRawVarint64(val); 1041 } 1042 } 1043 1044 /** 1045 * Write a single proto "int32" type field value. 1046 * 1047 * <p>Note that these are stored in memory as signed values and written as unsigned 1048 * varints, which if negative, are 10 bytes long. If you know the data is likely 1049 * to be negative, use "sint32". 1050 * 1051 * @deprecated Use {@link #write(long, int)} instead. 1052 * @hide 1053 */ 1054 @Deprecated writeInt32(long fieldId, int val)1055 public void writeInt32(long fieldId, int val) { 1056 assertNotCompacted(); 1057 final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_INT32); 1058 1059 writeInt32Impl(id, val); 1060 } 1061 writeInt32Impl(int id, int val)1062 private void writeInt32Impl(int id, int val) { 1063 if (val != 0) { 1064 writeTag(id, WIRE_TYPE_VARINT); 1065 writeUnsignedVarintFromSignedInt(val); 1066 } 1067 } 1068 1069 /** 1070 * Write a single repeated proto "int32" type field value. 1071 * 1072 * <p>Note that these are stored in memory as signed values and written as unsigned 1073 * varints, which if negative, are 10 bytes long. If you know the data is likely 1074 * to be negative, use "sint32". 1075 * 1076 * @deprecated Use {@link #write(long, int)} instead. 1077 * @hide 1078 */ 1079 @Deprecated writeRepeatedInt32(long fieldId, int val)1080 public void writeRepeatedInt32(long fieldId, int val) { 1081 assertNotCompacted(); 1082 final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_INT32); 1083 1084 writeRepeatedInt32Impl(id, val); 1085 } 1086 writeRepeatedInt32Impl(int id, int val)1087 private void writeRepeatedInt32Impl(int id, int val) { 1088 writeTag(id, WIRE_TYPE_VARINT); 1089 writeUnsignedVarintFromSignedInt(val); 1090 } 1091 1092 /** 1093 * Write a list of packed proto "int32" type field value. 1094 * 1095 * <p>Note that these are stored in memory as signed values and written as unsigned 1096 * varints, which if negative, are 10 bytes long. If you know the data is likely 1097 * to be negative, use "sint32". 1098 * 1099 * @deprecated Use {@link #write(long, int)} instead. 1100 * @hide 1101 */ 1102 @Deprecated writePackedInt32(long fieldId, @Nullable int[] val)1103 public void writePackedInt32(long fieldId, @Nullable int[] val) { 1104 assertNotCompacted(); 1105 final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_INT32); 1106 1107 final int N = val != null ? val.length : 0; 1108 if (N > 0) { 1109 int size = 0; 1110 for (int i=0; i<N; i++) { 1111 final int v = val[i]; 1112 size += v >= 0 ? EncodedBuffer.getRawVarint32Size(v) : 10; 1113 } 1114 writeKnownLengthHeader(id, size); 1115 for (int i=0; i<N; i++) { 1116 writeUnsignedVarintFromSignedInt(val[i]); 1117 } 1118 } 1119 } 1120 1121 // 1122 // proto3 type: int64 1123 // java type: int 1124 // signed/unsigned: signed 1125 // encoding: varint 1126 // wire type: WIRE_TYPE_VARINT 1127 // 1128 1129 /** 1130 * Write a single proto "int64" type field value. 1131 * 1132 * @deprecated Use {@link #write(long, long)} instead. 1133 * @hide 1134 */ 1135 @Deprecated writeInt64(long fieldId, long val)1136 public void writeInt64(long fieldId, long val) { 1137 assertNotCompacted(); 1138 final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_INT64); 1139 1140 writeInt64Impl(id, val); 1141 } 1142 writeInt64Impl(int id, long val)1143 private void writeInt64Impl(int id, long val) { 1144 if (val != 0) { 1145 writeTag(id, WIRE_TYPE_VARINT); 1146 mBuffer.writeRawVarint64(val); 1147 } 1148 } 1149 1150 /** 1151 * Write a single repeated proto "int64" type field value. 1152 * 1153 * @deprecated Use {@link #write(long, long)} instead. 1154 * @hide 1155 */ 1156 @Deprecated writeRepeatedInt64(long fieldId, long val)1157 public void writeRepeatedInt64(long fieldId, long val) { 1158 assertNotCompacted(); 1159 final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_INT64); 1160 1161 writeRepeatedInt64Impl(id, val); 1162 } 1163 writeRepeatedInt64Impl(int id, long val)1164 private void writeRepeatedInt64Impl(int id, long val) { 1165 writeTag(id, WIRE_TYPE_VARINT); 1166 mBuffer.writeRawVarint64(val); 1167 } 1168 1169 /** 1170 * Write a list of packed proto "int64" type field value. 1171 * 1172 * @deprecated Use {@link #write(long, long)} instead. 1173 * @hide 1174 */ 1175 @Deprecated writePackedInt64(long fieldId, @Nullable long[] val)1176 public void writePackedInt64(long fieldId, @Nullable long[] val) { 1177 assertNotCompacted(); 1178 final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_INT64); 1179 1180 final int N = val != null ? val.length : 0; 1181 if (N > 0) { 1182 int size = 0; 1183 for (int i=0; i<N; i++) { 1184 size += EncodedBuffer.getRawVarint64Size(val[i]); 1185 } 1186 writeKnownLengthHeader(id, size); 1187 for (int i=0; i<N; i++) { 1188 mBuffer.writeRawVarint64(val[i]); 1189 } 1190 } 1191 } 1192 1193 // 1194 // proto3 type: uint32 1195 // java type: int 1196 // signed/unsigned: unsigned 1197 // encoding: varint 1198 // wire type: WIRE_TYPE_VARINT 1199 // 1200 1201 /** 1202 * Write a single proto "uint32" type field value. 1203 * 1204 * @deprecated Use {@link #write(long, int)} instead. 1205 * @hide 1206 */ 1207 @Deprecated writeUInt32(long fieldId, int val)1208 public void writeUInt32(long fieldId, int val) { 1209 assertNotCompacted(); 1210 final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_UINT32); 1211 1212 writeUInt32Impl(id, val); 1213 } 1214 writeUInt32Impl(int id, int val)1215 private void writeUInt32Impl(int id, int val) { 1216 if (val != 0) { 1217 writeTag(id, WIRE_TYPE_VARINT); 1218 mBuffer.writeRawVarint32(val); 1219 } 1220 } 1221 1222 /** 1223 * Write a single repeated proto "uint32" type field value. 1224 * 1225 * @deprecated Use {@link #write(long, int)} instead. 1226 * @hide 1227 */ 1228 @Deprecated writeRepeatedUInt32(long fieldId, int val)1229 public void writeRepeatedUInt32(long fieldId, int val) { 1230 assertNotCompacted(); 1231 final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_UINT32); 1232 1233 writeRepeatedUInt32Impl(id, val); 1234 } 1235 writeRepeatedUInt32Impl(int id, int val)1236 private void writeRepeatedUInt32Impl(int id, int val) { 1237 writeTag(id, WIRE_TYPE_VARINT); 1238 mBuffer.writeRawVarint32(val); 1239 } 1240 1241 /** 1242 * Write a list of packed proto "uint32" type field value. 1243 * 1244 * @deprecated Use {@link #write(long, int)} instead. 1245 * @hide 1246 */ 1247 @Deprecated writePackedUInt32(long fieldId, @Nullable int[] val)1248 public void writePackedUInt32(long fieldId, @Nullable int[] val) { 1249 assertNotCompacted(); 1250 final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_UINT32); 1251 1252 final int N = val != null ? val.length : 0; 1253 if (N > 0) { 1254 int size = 0; 1255 for (int i=0; i<N; i++) { 1256 size += EncodedBuffer.getRawVarint32Size(val[i]); 1257 } 1258 writeKnownLengthHeader(id, size); 1259 for (int i=0; i<N; i++) { 1260 mBuffer.writeRawVarint32(val[i]); 1261 } 1262 } 1263 } 1264 1265 // 1266 // proto3 type: uint64 1267 // java type: int 1268 // signed/unsigned: unsigned 1269 // encoding: varint 1270 // wire type: WIRE_TYPE_VARINT 1271 // 1272 1273 /** 1274 * Write a single proto "uint64" type field value. 1275 * 1276 * @deprecated Use {@link #write(long, long)} instead. 1277 * @hide 1278 */ 1279 @Deprecated writeUInt64(long fieldId, long val)1280 public void writeUInt64(long fieldId, long val) { 1281 assertNotCompacted(); 1282 final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_UINT64); 1283 1284 writeUInt64Impl(id, val); 1285 } 1286 writeUInt64Impl(int id, long val)1287 private void writeUInt64Impl(int id, long val) { 1288 if (val != 0) { 1289 writeTag(id, WIRE_TYPE_VARINT); 1290 mBuffer.writeRawVarint64(val); 1291 } 1292 } 1293 1294 /** 1295 * Write a single proto "uint64" type field value. 1296 * 1297 * @deprecated Use {@link #write(long, long)} instead. 1298 * @hide 1299 */ 1300 @Deprecated writeRepeatedUInt64(long fieldId, long val)1301 public void writeRepeatedUInt64(long fieldId, long val) { 1302 assertNotCompacted(); 1303 final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_UINT64); 1304 1305 writeRepeatedUInt64Impl(id, val); 1306 } 1307 writeRepeatedUInt64Impl(int id, long val)1308 private void writeRepeatedUInt64Impl(int id, long val) { 1309 writeTag(id, WIRE_TYPE_VARINT); 1310 mBuffer.writeRawVarint64(val); 1311 } 1312 1313 /** 1314 * Write a single proto "uint64" type field value. 1315 * 1316 * @deprecated Use {@link #write(long, long)} instead. 1317 * @hide 1318 */ 1319 @Deprecated writePackedUInt64(long fieldId, @Nullable long[] val)1320 public void writePackedUInt64(long fieldId, @Nullable long[] val) { 1321 assertNotCompacted(); 1322 final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_UINT64); 1323 1324 final int N = val != null ? val.length : 0; 1325 if (N > 0) { 1326 int size = 0; 1327 for (int i=0; i<N; i++) { 1328 size += EncodedBuffer.getRawVarint64Size(val[i]); 1329 } 1330 writeKnownLengthHeader(id, size); 1331 for (int i=0; i<N; i++) { 1332 mBuffer.writeRawVarint64(val[i]); 1333 } 1334 } 1335 } 1336 1337 // 1338 // proto3 type: sint32 1339 // java type: int 1340 // signed/unsigned: signed 1341 // encoding: zig-zag 1342 // wire type: WIRE_TYPE_VARINT 1343 // 1344 1345 /** 1346 * Write a single proto "sint32" type field value. 1347 * 1348 * @deprecated Use {@link #write(long, int)} instead. 1349 * @hide 1350 */ 1351 @Deprecated writeSInt32(long fieldId, int val)1352 public void writeSInt32(long fieldId, int val) { 1353 assertNotCompacted(); 1354 final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_SINT32); 1355 1356 writeSInt32Impl(id, val); 1357 } 1358 writeSInt32Impl(int id, int val)1359 private void writeSInt32Impl(int id, int val) { 1360 if (val != 0) { 1361 writeTag(id, WIRE_TYPE_VARINT); 1362 mBuffer.writeRawZigZag32(val); 1363 } 1364 } 1365 1366 /** 1367 * Write a single repeated proto "sint32" type field value. 1368 * 1369 * @deprecated Use {@link #write(long, int)} instead. 1370 * @hide 1371 */ 1372 @Deprecated writeRepeatedSInt32(long fieldId, int val)1373 public void writeRepeatedSInt32(long fieldId, int val) { 1374 assertNotCompacted(); 1375 final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_SINT32); 1376 1377 writeRepeatedSInt32Impl(id, val); 1378 } 1379 writeRepeatedSInt32Impl(int id, int val)1380 private void writeRepeatedSInt32Impl(int id, int val) { 1381 writeTag(id, WIRE_TYPE_VARINT); 1382 mBuffer.writeRawZigZag32(val); 1383 } 1384 1385 /** 1386 * Write a list of packed proto "sint32" type field value. 1387 * 1388 * @deprecated Use {@link #write(long, int)} instead. 1389 * @hide 1390 */ 1391 @Deprecated writePackedSInt32(long fieldId, @Nullable int[] val)1392 public void writePackedSInt32(long fieldId, @Nullable int[] val) { 1393 assertNotCompacted(); 1394 final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_SINT32); 1395 1396 final int N = val != null ? val.length : 0; 1397 if (N > 0) { 1398 int size = 0; 1399 for (int i=0; i<N; i++) { 1400 size += EncodedBuffer.getRawZigZag32Size(val[i]); 1401 } 1402 writeKnownLengthHeader(id, size); 1403 for (int i=0; i<N; i++) { 1404 mBuffer.writeRawZigZag32(val[i]); 1405 } 1406 } 1407 } 1408 1409 // 1410 // proto3 type: sint64 1411 // java type: int 1412 // signed/unsigned: signed 1413 // encoding: zig-zag 1414 // wire type: WIRE_TYPE_VARINT 1415 // 1416 1417 /** 1418 * Write a single proto "sint64" type field value. 1419 * 1420 * @deprecated Use {@link #write(long, long)} instead. 1421 * @hide 1422 */ 1423 @Deprecated writeSInt64(long fieldId, long val)1424 public void writeSInt64(long fieldId, long val) { 1425 assertNotCompacted(); 1426 final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_SINT64); 1427 1428 writeSInt64Impl(id, val); 1429 } 1430 writeSInt64Impl(int id, long val)1431 private void writeSInt64Impl(int id, long val) { 1432 if (val != 0) { 1433 writeTag(id, WIRE_TYPE_VARINT); 1434 mBuffer.writeRawZigZag64(val); 1435 } 1436 } 1437 1438 /** 1439 * Write a single repeated proto "sint64" type field value. 1440 * 1441 * @deprecated Use {@link #write(long, long)} instead. 1442 * @hide 1443 */ 1444 @Deprecated writeRepeatedSInt64(long fieldId, long val)1445 public void writeRepeatedSInt64(long fieldId, long val) { 1446 assertNotCompacted(); 1447 final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_SINT64); 1448 1449 writeRepeatedSInt64Impl(id, val); 1450 } 1451 writeRepeatedSInt64Impl(int id, long val)1452 private void writeRepeatedSInt64Impl(int id, long val) { 1453 writeTag(id, WIRE_TYPE_VARINT); 1454 mBuffer.writeRawZigZag64(val); 1455 } 1456 1457 /** 1458 * Write a list of packed proto "sint64" type field value. 1459 * 1460 * @deprecated Use {@link #write(long, long)} instead. 1461 * @hide 1462 */ 1463 @Deprecated writePackedSInt64(long fieldId, @Nullable long[] val)1464 public void writePackedSInt64(long fieldId, @Nullable long[] val) { 1465 assertNotCompacted(); 1466 final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_SINT64); 1467 1468 final int N = val != null ? val.length : 0; 1469 if (N > 0) { 1470 int size = 0; 1471 for (int i=0; i<N; i++) { 1472 size += EncodedBuffer.getRawZigZag64Size(val[i]); 1473 } 1474 writeKnownLengthHeader(id, size); 1475 for (int i=0; i<N; i++) { 1476 mBuffer.writeRawZigZag64(val[i]); 1477 } 1478 } 1479 } 1480 1481 // 1482 // proto3 type: fixed32 1483 // java type: int 1484 // encoding: little endian 1485 // wire type: WIRE_TYPE_FIXED32 1486 // 1487 1488 /** 1489 * Write a single proto "fixed32" type field value. 1490 * 1491 * @deprecated Use {@link #write(long, int)} instead. 1492 * @hide 1493 */ 1494 @Deprecated writeFixed32(long fieldId, int val)1495 public void writeFixed32(long fieldId, int val) { 1496 assertNotCompacted(); 1497 final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_FIXED32); 1498 1499 writeFixed32Impl(id, val); 1500 } 1501 writeFixed32Impl(int id, int val)1502 private void writeFixed32Impl(int id, int val) { 1503 if (val != 0) { 1504 writeTag(id, WIRE_TYPE_FIXED32); 1505 mBuffer.writeRawFixed32(val); 1506 } 1507 } 1508 1509 /** 1510 * Write a single repeated proto "fixed32" type field value. 1511 * 1512 * @deprecated Use {@link #write(long, int)} instead. 1513 * @hide 1514 */ 1515 @Deprecated writeRepeatedFixed32(long fieldId, int val)1516 public void writeRepeatedFixed32(long fieldId, int val) { 1517 assertNotCompacted(); 1518 final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_FIXED32); 1519 1520 writeRepeatedFixed32Impl(id, val); 1521 } 1522 writeRepeatedFixed32Impl(int id, int val)1523 private void writeRepeatedFixed32Impl(int id, int val) { 1524 writeTag(id, WIRE_TYPE_FIXED32); 1525 mBuffer.writeRawFixed32(val); 1526 } 1527 1528 /** 1529 * Write a list of packed proto "fixed32" type field value. 1530 * 1531 * @deprecated Use {@link #write(long, int)} instead. 1532 * @hide 1533 */ 1534 @Deprecated writePackedFixed32(long fieldId, @Nullable int[] val)1535 public void writePackedFixed32(long fieldId, @Nullable int[] val) { 1536 assertNotCompacted(); 1537 final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_FIXED32); 1538 1539 final int N = val != null ? val.length : 0; 1540 if (N > 0) { 1541 writeKnownLengthHeader(id, N * 4); 1542 for (int i=0; i<N; i++) { 1543 mBuffer.writeRawFixed32(val[i]); 1544 } 1545 } 1546 } 1547 1548 // 1549 // proto3 type: fixed64 1550 // java type: long 1551 // encoding: fixed64 1552 // wire type: WIRE_TYPE_FIXED64 1553 // 1554 1555 /** 1556 * Write a single proto "fixed64" type field value. 1557 * 1558 * @deprecated Use {@link #write(long, long)} instead. 1559 * @hide 1560 */ 1561 @Deprecated writeFixed64(long fieldId, long val)1562 public void writeFixed64(long fieldId, long val) { 1563 assertNotCompacted(); 1564 final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_FIXED64); 1565 1566 writeFixed64Impl(id, val); 1567 } 1568 writeFixed64Impl(int id, long val)1569 private void writeFixed64Impl(int id, long val) { 1570 if (val != 0) { 1571 writeTag(id, WIRE_TYPE_FIXED64); 1572 mBuffer.writeRawFixed64(val); 1573 } 1574 } 1575 1576 /** 1577 * Write a single repeated proto "fixed64" type field value. 1578 * 1579 * @deprecated Use {@link #write(long, long)} instead. 1580 * @hide 1581 */ 1582 @Deprecated writeRepeatedFixed64(long fieldId, long val)1583 public void writeRepeatedFixed64(long fieldId, long val) { 1584 assertNotCompacted(); 1585 final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_FIXED64); 1586 1587 writeRepeatedFixed64Impl(id, val); 1588 } 1589 writeRepeatedFixed64Impl(int id, long val)1590 private void writeRepeatedFixed64Impl(int id, long val) { 1591 writeTag(id, WIRE_TYPE_FIXED64); 1592 mBuffer.writeRawFixed64(val); 1593 } 1594 1595 /** 1596 * Write a list of packed proto "fixed64" type field value. 1597 * 1598 * @deprecated Use {@link #write(long, long)} instead. 1599 * @hide 1600 */ 1601 @Deprecated writePackedFixed64(long fieldId, @Nullable long[] val)1602 public void writePackedFixed64(long fieldId, @Nullable long[] val) { 1603 assertNotCompacted(); 1604 final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_FIXED64); 1605 1606 final int N = val != null ? val.length : 0; 1607 if (N > 0) { 1608 writeKnownLengthHeader(id, N * 8); 1609 for (int i=0; i<N; i++) { 1610 mBuffer.writeRawFixed64(val[i]); 1611 } 1612 } 1613 } 1614 1615 // 1616 // proto3 type: sfixed32 1617 // java type: int 1618 // encoding: little endian 1619 // wire type: WIRE_TYPE_FIXED32 1620 // 1621 /** 1622 * Write a single proto "sfixed32" type field value. 1623 * 1624 * @deprecated Use {@link #write(long, int)} instead. 1625 * @hide 1626 */ 1627 @Deprecated writeSFixed32(long fieldId, int val)1628 public void writeSFixed32(long fieldId, int val) { 1629 assertNotCompacted(); 1630 final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_SFIXED32); 1631 1632 writeSFixed32Impl(id, val); 1633 } 1634 writeSFixed32Impl(int id, int val)1635 private void writeSFixed32Impl(int id, int val) { 1636 if (val != 0) { 1637 writeTag(id, WIRE_TYPE_FIXED32); 1638 mBuffer.writeRawFixed32(val); 1639 } 1640 } 1641 1642 /** 1643 * Write a single repeated proto "sfixed32" type field value. 1644 * 1645 * @deprecated Use {@link #write(long, int)} instead. 1646 * @hide 1647 */ 1648 @Deprecated writeRepeatedSFixed32(long fieldId, int val)1649 public void writeRepeatedSFixed32(long fieldId, int val) { 1650 assertNotCompacted(); 1651 final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_SFIXED32); 1652 1653 writeRepeatedSFixed32Impl(id, val); 1654 } 1655 writeRepeatedSFixed32Impl(int id, int val)1656 private void writeRepeatedSFixed32Impl(int id, int val) { 1657 writeTag(id, WIRE_TYPE_FIXED32); 1658 mBuffer.writeRawFixed32(val); 1659 } 1660 1661 /** 1662 * Write a list of packed proto "sfixed32" type field value. 1663 * 1664 * @deprecated Use {@link #write(long, int)} instead. 1665 * @hide 1666 */ 1667 @Deprecated writePackedSFixed32(long fieldId, @Nullable int[] val)1668 public void writePackedSFixed32(long fieldId, @Nullable int[] val) { 1669 assertNotCompacted(); 1670 final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_SFIXED32); 1671 1672 final int N = val != null ? val.length : 0; 1673 if (N > 0) { 1674 writeKnownLengthHeader(id, N * 4); 1675 for (int i=0; i<N; i++) { 1676 mBuffer.writeRawFixed32(val[i]); 1677 } 1678 } 1679 } 1680 1681 // 1682 // proto3 type: sfixed64 1683 // java type: long 1684 // encoding: little endian 1685 // wire type: WIRE_TYPE_FIXED64 1686 // 1687 1688 /** 1689 * Write a single proto "sfixed64" type field value. 1690 * 1691 * @deprecated Use {@link #write(long, long)} instead. 1692 * @hide 1693 */ 1694 @Deprecated writeSFixed64(long fieldId, long val)1695 public void writeSFixed64(long fieldId, long val) { 1696 assertNotCompacted(); 1697 final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_SFIXED64); 1698 1699 writeSFixed64Impl(id, val); 1700 } 1701 writeSFixed64Impl(int id, long val)1702 private void writeSFixed64Impl(int id, long val) { 1703 if (val != 0) { 1704 writeTag(id, WIRE_TYPE_FIXED64); 1705 mBuffer.writeRawFixed64(val); 1706 } 1707 } 1708 1709 /** 1710 * Write a single repeated proto "sfixed64" type field value. 1711 * 1712 * @deprecated Use {@link #write(long, long)} instead. 1713 * @hide 1714 */ 1715 @Deprecated writeRepeatedSFixed64(long fieldId, long val)1716 public void writeRepeatedSFixed64(long fieldId, long val) { 1717 assertNotCompacted(); 1718 final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_SFIXED64); 1719 1720 writeRepeatedSFixed64Impl(id, val); 1721 } 1722 writeRepeatedSFixed64Impl(int id, long val)1723 private void writeRepeatedSFixed64Impl(int id, long val) { 1724 writeTag(id, WIRE_TYPE_FIXED64); 1725 mBuffer.writeRawFixed64(val); 1726 } 1727 1728 /** 1729 * Write a list of packed proto "sfixed64" type field value. 1730 * 1731 * @deprecated Use {@link #write(long, long)} instead. 1732 * @hide 1733 */ 1734 @Deprecated writePackedSFixed64(long fieldId, @Nullable long[] val)1735 public void writePackedSFixed64(long fieldId, @Nullable long[] val) { 1736 assertNotCompacted(); 1737 final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_SFIXED64); 1738 1739 final int N = val != null ? val.length : 0; 1740 if (N > 0) { 1741 writeKnownLengthHeader(id, N * 8); 1742 for (int i=0; i<N; i++) { 1743 mBuffer.writeRawFixed64(val[i]); 1744 } 1745 } 1746 } 1747 1748 // 1749 // proto3 type: bool 1750 // java type: boolean 1751 // encoding: varint 1752 // wire type: WIRE_TYPE_VARINT 1753 // 1754 1755 /** 1756 * Write a single proto "bool" type field value. 1757 * 1758 * @deprecated Use {@link #write(long, boolean)} instead. 1759 * @hide 1760 */ 1761 @Deprecated writeBool(long fieldId, boolean val)1762 public void writeBool(long fieldId, boolean val) { 1763 assertNotCompacted(); 1764 final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_BOOL); 1765 1766 writeBoolImpl(id, val); 1767 } 1768 writeBoolImpl(int id, boolean val)1769 private void writeBoolImpl(int id, boolean val) { 1770 if (val) { 1771 writeTag(id, WIRE_TYPE_VARINT); 1772 // 0 and 1 are the same as their varint counterparts 1773 mBuffer.writeRawByte((byte)1); 1774 } 1775 } 1776 1777 /** 1778 * Write a single repeated proto "bool" type field value. 1779 * 1780 * @deprecated Use {@link #write(long, boolean)} instead. 1781 * @hide 1782 */ 1783 @Deprecated writeRepeatedBool(long fieldId, boolean val)1784 public void writeRepeatedBool(long fieldId, boolean val) { 1785 assertNotCompacted(); 1786 final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_BOOL); 1787 1788 writeRepeatedBoolImpl(id, val); 1789 } 1790 writeRepeatedBoolImpl(int id, boolean val)1791 private void writeRepeatedBoolImpl(int id, boolean val) { 1792 writeTag(id, WIRE_TYPE_VARINT); 1793 mBuffer.writeRawByte((byte)(val ? 1 : 0)); 1794 } 1795 1796 /** 1797 * Write a list of packed proto "bool" type field value. 1798 * 1799 * @deprecated Use {@link #write(long, boolean)} instead. 1800 * @hide 1801 */ 1802 @Deprecated writePackedBool(long fieldId, @Nullable boolean[] val)1803 public void writePackedBool(long fieldId, @Nullable boolean[] val) { 1804 assertNotCompacted(); 1805 final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_BOOL); 1806 1807 final int N = val != null ? val.length : 0; 1808 if (N > 0) { 1809 // Write the header 1810 writeKnownLengthHeader(id, N); 1811 1812 // Write the data 1813 for (int i=0; i<N; i++) { 1814 // 0 and 1 are the same as their varint counterparts 1815 mBuffer.writeRawByte((byte)(val[i] ? 1 : 0)); 1816 } 1817 } 1818 } 1819 1820 // 1821 // proto3 type: string 1822 // java type: String 1823 // encoding: utf-8 1824 // wire type: WIRE_TYPE_LENGTH_DELIMITED 1825 // 1826 1827 /** 1828 * Write a single proto "string" type field value. 1829 * 1830 * @deprecated Use {@link #write(long, String)} instead. 1831 * @hide 1832 */ 1833 @Deprecated writeString(long fieldId, @Nullable String val)1834 public void writeString(long fieldId, @Nullable String val) { 1835 assertNotCompacted(); 1836 final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_STRING); 1837 1838 writeStringImpl(id, val); 1839 } 1840 writeStringImpl(int id, String val)1841 private void writeStringImpl(int id, String val) { 1842 if (val != null && val.length() > 0) { 1843 writeUtf8String(id, val); 1844 } 1845 } 1846 1847 /** 1848 * Write a single repeated proto "string" type field value. 1849 * 1850 * @deprecated Use {@link #write(long, String)} instead. 1851 * @hide 1852 */ 1853 @Deprecated writeRepeatedString(long fieldId, @Nullable String val)1854 public void writeRepeatedString(long fieldId, @Nullable String val) { 1855 assertNotCompacted(); 1856 final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_STRING); 1857 1858 writeRepeatedStringImpl(id, val); 1859 } 1860 writeRepeatedStringImpl(int id, String val)1861 private void writeRepeatedStringImpl(int id, String val) { 1862 if (val == null || val.length() == 0) { 1863 writeKnownLengthHeader(id, 0); 1864 } else { 1865 writeUtf8String(id, val); 1866 } 1867 } 1868 1869 /** 1870 * Write a list of packed proto "string" type field value. 1871 */ writeUtf8String(int id, String val)1872 private void writeUtf8String(int id, String val) { 1873 // TODO: Is it worth converting by hand in order to not allocate? 1874 try { 1875 final byte[] buf = val.getBytes("UTF-8"); 1876 writeKnownLengthHeader(id, buf.length); 1877 mBuffer.writeRawBuffer(buf); 1878 } catch (UnsupportedEncodingException ex) { 1879 throw new RuntimeException("not possible"); 1880 } 1881 } 1882 1883 // 1884 // proto3 type: bytes 1885 // java type: byte[] 1886 // encoding: varint 1887 // wire type: WIRE_TYPE_VARINT 1888 // 1889 1890 /** 1891 * Write a single proto "bytes" type field value. 1892 * 1893 * @deprecated Use {@link #write(long, byte[])} instead. 1894 * @hide 1895 */ 1896 @Deprecated writeBytes(long fieldId, @Nullable byte[] val)1897 public void writeBytes(long fieldId, @Nullable byte[] val) { 1898 assertNotCompacted(); 1899 final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_BYTES); 1900 1901 writeBytesImpl(id, val); 1902 } 1903 writeBytesImpl(int id, byte[] val)1904 private void writeBytesImpl(int id, byte[] val) { 1905 if (val != null && val.length > 0) { 1906 writeKnownLengthHeader(id, val.length); 1907 mBuffer.writeRawBuffer(val); 1908 } 1909 } 1910 1911 /** 1912 * Write a single repeated proto "bytes" type field value. 1913 * 1914 * @deprecated Use {@link #write(long, byte[])} instead. 1915 * @hide 1916 */ 1917 @Deprecated writeRepeatedBytes(long fieldId, @Nullable byte[] val)1918 public void writeRepeatedBytes(long fieldId, @Nullable byte[] val) { 1919 assertNotCompacted(); 1920 final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_BYTES); 1921 1922 writeRepeatedBytesImpl(id, val); 1923 } 1924 writeRepeatedBytesImpl(int id, byte[] val)1925 private void writeRepeatedBytesImpl(int id, byte[] val) { 1926 writeKnownLengthHeader(id, val == null ? 0 : val.length); 1927 mBuffer.writeRawBuffer(val); 1928 } 1929 1930 // 1931 // proto3 type: enum 1932 // java type: int 1933 // signed/unsigned: unsigned 1934 // encoding: varint 1935 // wire type: WIRE_TYPE_VARINT 1936 // 1937 1938 /** 1939 * Write a single proto enum type field value. 1940 * 1941 * @deprecated Use {@link #write(long, int)} instead. 1942 * @hide 1943 */ 1944 @Deprecated writeEnum(long fieldId, int val)1945 public void writeEnum(long fieldId, int val) { 1946 assertNotCompacted(); 1947 final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_ENUM); 1948 1949 writeEnumImpl(id, val); 1950 } 1951 writeEnumImpl(int id, int val)1952 private void writeEnumImpl(int id, int val) { 1953 if (val != 0) { 1954 writeTag(id, WIRE_TYPE_VARINT); 1955 writeUnsignedVarintFromSignedInt(val); 1956 } 1957 } 1958 1959 /** 1960 * Write a single repeated proto enum type field value. 1961 * 1962 * @deprecated Use {@link #write(long, int)} instead. 1963 * @hide 1964 */ 1965 @Deprecated writeRepeatedEnum(long fieldId, int val)1966 public void writeRepeatedEnum(long fieldId, int val) { 1967 assertNotCompacted(); 1968 final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_ENUM); 1969 1970 writeRepeatedEnumImpl(id, val); 1971 } 1972 writeRepeatedEnumImpl(int id, int val)1973 private void writeRepeatedEnumImpl(int id, int val) { 1974 writeTag(id, WIRE_TYPE_VARINT); 1975 writeUnsignedVarintFromSignedInt(val); 1976 } 1977 1978 /** 1979 * Write a list of packed proto enum type field value. 1980 * 1981 * @deprecated Use {@link #write(long, int)} instead. 1982 * @hide 1983 */ 1984 @Deprecated writePackedEnum(long fieldId, @Nullable int[] val)1985 public void writePackedEnum(long fieldId, @Nullable int[] val) { 1986 assertNotCompacted(); 1987 final int id = checkFieldId(fieldId, FIELD_COUNT_PACKED | FIELD_TYPE_ENUM); 1988 1989 final int N = val != null ? val.length : 0; 1990 if (N > 0) { 1991 int size = 0; 1992 for (int i=0; i<N; i++) { 1993 final int v = val[i]; 1994 size += v >= 0 ? EncodedBuffer.getRawVarint32Size(v) : 10; 1995 } 1996 writeKnownLengthHeader(id, size); 1997 for (int i=0; i<N; i++) { 1998 writeUnsignedVarintFromSignedInt(val[i]); 1999 } 2000 } 2001 } 2002 2003 2004 /** 2005 * Start a child object. 2006 * 2007 * Returns a token which should be passed to endObject. Calls to endObject must be 2008 * nested properly. 2009 * 2010 * @deprecated Use {@link #start(long)} instead. 2011 * @hide 2012 */ 2013 @Deprecated startObject(long fieldId)2014 public long startObject(long fieldId) { 2015 assertNotCompacted(); 2016 final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_MESSAGE); 2017 2018 return startObjectImpl(id, false); 2019 } 2020 2021 /** 2022 * End a child object. Pass in the token from the correspoinding startObject call. 2023 * 2024 * @deprecated Use {@link #end(long)} instead. 2025 * @hide 2026 */ 2027 @Deprecated endObject(long token)2028 public void endObject(long token) { 2029 assertNotCompacted(); 2030 2031 endObjectImpl(token, false); 2032 } 2033 2034 /** 2035 * Start a repeated child object. 2036 * 2037 * Returns a token which should be passed to endObject. Calls to endObject must be 2038 * nested properly. 2039 * 2040 * @deprecated Use {@link #start(long)} instead. 2041 * @hide 2042 */ 2043 @Deprecated startRepeatedObject(long fieldId)2044 public long startRepeatedObject(long fieldId) { 2045 assertNotCompacted(); 2046 final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_MESSAGE); 2047 2048 return startObjectImpl(id, true); 2049 } 2050 2051 /** 2052 * End a child object. Pass in the token from the correspoinding startRepeatedObject call. 2053 * 2054 * @deprecated Use {@link #end(long)} instead. 2055 * @hide 2056 */ 2057 @Deprecated endRepeatedObject(long token)2058 public void endRepeatedObject(long token) { 2059 assertNotCompacted(); 2060 2061 endObjectImpl(token, true); 2062 } 2063 2064 /** 2065 * Common implementation of startObject and startRepeatedObject. 2066 */ startObjectImpl(final int id, boolean repeated)2067 private long startObjectImpl(final int id, boolean repeated) { 2068 writeTag(id, WIRE_TYPE_LENGTH_DELIMITED); 2069 final int sizePos = mBuffer.getWritePos(); 2070 mDepth++; 2071 mNextObjectId--; 2072 2073 // Write the previous token, giving us a stack of expected tokens. 2074 // After endObject returns, the first fixed32 becomeschildRawSize (set in endObject) 2075 // and the second one becomes childEncodedSize (set in editEncodedSize). 2076 mBuffer.writeRawFixed32((int)(mExpectedObjectToken >> 32)); 2077 mBuffer.writeRawFixed32((int)mExpectedObjectToken); 2078 2079 long old = mExpectedObjectToken; 2080 2081 mExpectedObjectToken = makeToken(getTagSize(id), repeated, mDepth, mNextObjectId, sizePos); 2082 return mExpectedObjectToken; 2083 } 2084 2085 /** 2086 * Common implementation of endObject and endRepeatedObject. 2087 */ endObjectImpl(long token, boolean repeated)2088 private void endObjectImpl(long token, boolean repeated) { 2089 // The upper 32 bits of the token is the depth of startObject / 2090 // endObject calls. We could get aritrarily sophisticated, but 2091 // that's enough to prevent the common error of missing an 2092 // endObject somewhere. 2093 // The lower 32 bits of the token is the offset in the buffer 2094 // at which to write the size. 2095 final int depth = getDepthFromToken(token); 2096 final boolean expectedRepeated = getRepeatedFromToken(token); 2097 final int sizePos = getOffsetFromToken(token); 2098 final int childRawSize = mBuffer.getWritePos() - sizePos - 8; 2099 2100 if (repeated != expectedRepeated) { 2101 if (repeated) { 2102 throw new IllegalArgumentException("endRepeatedObject called where endObject should" 2103 + " have been"); 2104 } else { 2105 throw new IllegalArgumentException("endObject called where endRepeatedObject should" 2106 + " have been"); 2107 } 2108 } 2109 2110 // Check that we're getting the token and depth that we are expecting. 2111 if ((mDepth & 0x01ff) != depth || mExpectedObjectToken != token) { 2112 // This text of exception is united tested. That test also implicity checks 2113 // that we're tracking the objectIds and depths correctly. 2114 throw new IllegalArgumentException("Mismatched startObject/endObject calls." 2115 + " Current depth " + mDepth 2116 + " token=" + token2String(token) 2117 + " expectedToken=" + token2String(mExpectedObjectToken)); 2118 } 2119 2120 // Get the next expected token that we stashed away in the buffer. 2121 mExpectedObjectToken = (((long)mBuffer.getRawFixed32At(sizePos)) << 32) 2122 | (0x0ffffffffL & (long)mBuffer.getRawFixed32At(sizePos+4)); 2123 2124 mDepth--; 2125 if (childRawSize > 0) { 2126 mBuffer.editRawFixed32(sizePos, -childRawSize); 2127 mBuffer.editRawFixed32(sizePos+4, -1); 2128 } else if (repeated) { 2129 mBuffer.editRawFixed32(sizePos, 0); 2130 mBuffer.editRawFixed32(sizePos+4, 0); 2131 } else { 2132 // The object has no data. Don't include it. 2133 mBuffer.rewindWriteTo(sizePos - getTagSizeFromToken(token)); 2134 } 2135 } 2136 2137 /** 2138 * Write an object that has already been flattened. 2139 * 2140 * @deprecated Use {@link #write(long, byte[])} instead. 2141 * @hide 2142 */ 2143 @Deprecated writeObject(long fieldId, @Nullable byte[] value)2144 public void writeObject(long fieldId, @Nullable byte[] value) { 2145 assertNotCompacted(); 2146 final int id = checkFieldId(fieldId, FIELD_COUNT_SINGLE | FIELD_TYPE_MESSAGE); 2147 2148 writeObjectImpl(id, value); 2149 } 2150 writeObjectImpl(int id, byte[] value)2151 void writeObjectImpl(int id, byte[] value) { 2152 if (value != null && value.length != 0) { 2153 writeKnownLengthHeader(id, value.length); 2154 mBuffer.writeRawBuffer(value); 2155 } 2156 } 2157 2158 /** 2159 * Write an object that has already been flattened. 2160 * 2161 * @deprecated Use {@link #write(long, byte[])} instead. 2162 * @hide 2163 */ 2164 @Deprecated writeRepeatedObject(long fieldId, @Nullable byte[] value)2165 public void writeRepeatedObject(long fieldId, @Nullable byte[] value) { 2166 assertNotCompacted(); 2167 final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_MESSAGE); 2168 2169 writeRepeatedObjectImpl(id, value); 2170 } 2171 writeRepeatedObjectImpl(int id, byte[] value)2172 void writeRepeatedObjectImpl(int id, byte[] value) { 2173 writeKnownLengthHeader(id, value == null ? 0 : value.length); 2174 mBuffer.writeRawBuffer(value); 2175 } 2176 2177 // 2178 // Tags 2179 // 2180 2181 /** 2182 * Combine a fieldId (the field keys in the proto file) and the field flags. 2183 * Mostly useful for testing because the generated code contains the fieldId 2184 * constants. 2185 */ makeFieldId(int id, long fieldFlags)2186 public static long makeFieldId(int id, long fieldFlags) { 2187 return fieldFlags | (((long)id) & 0x0ffffffffL); 2188 } 2189 2190 /** 2191 * Validates that the fieldId provided is of the type and count from expectedType. 2192 * 2193 * <p>The type must match exactly to pass this check. 2194 * 2195 * <p>The count must match according to this truth table to pass the check: 2196 * 2197 * expectedFlags 2198 * UNKNOWN SINGLE REPEATED PACKED 2199 * fieldId 2200 * UNKNOWN true false false false 2201 * SINGLE x true false false 2202 * REPEATED x false true false 2203 * PACKED x false true true 2204 * 2205 * @throws {@link IllegalArgumentException} if it is not. 2206 * 2207 * @return The raw ID of that field. 2208 */ checkFieldId(long fieldId, long expectedFlags)2209 public static int checkFieldId(long fieldId, long expectedFlags) { 2210 final long fieldCount = fieldId & FIELD_COUNT_MASK; 2211 final long fieldType = fieldId & FIELD_TYPE_MASK; 2212 final long expectedCount = expectedFlags & FIELD_COUNT_MASK; 2213 final long expectedType = expectedFlags & FIELD_TYPE_MASK; 2214 if (((int)fieldId) == 0) { 2215 throw new IllegalArgumentException("Invalid proto field " + (int)fieldId 2216 + " fieldId=" + Long.toHexString(fieldId)); 2217 } 2218 if (fieldType != expectedType 2219 || !((fieldCount == expectedCount) 2220 || (fieldCount == FIELD_COUNT_PACKED 2221 && expectedCount == FIELD_COUNT_REPEATED))) { 2222 final String countString = getFieldCountString(fieldCount); 2223 final String typeString = getFieldTypeString(fieldType); 2224 if (typeString != null && countString != null) { 2225 final StringBuilder sb = new StringBuilder(); 2226 if (expectedType == FIELD_TYPE_MESSAGE) { 2227 sb.append("start"); 2228 } else { 2229 sb.append("write"); 2230 } 2231 sb.append(getFieldCountString(expectedCount)); 2232 sb.append(getFieldTypeString(expectedType)); 2233 sb.append(" called for field "); 2234 sb.append((int)fieldId); 2235 sb.append(" which should be used with "); 2236 if (fieldType == FIELD_TYPE_MESSAGE) { 2237 sb.append("start"); 2238 } else { 2239 sb.append("write"); 2240 } 2241 sb.append(countString); 2242 sb.append(typeString); 2243 if (fieldCount == FIELD_COUNT_PACKED) { 2244 sb.append(" or writeRepeated"); 2245 sb.append(typeString); 2246 } 2247 sb.append('.'); 2248 throw new IllegalArgumentException(sb.toString()); 2249 } else { 2250 final StringBuilder sb = new StringBuilder(); 2251 if (expectedType == FIELD_TYPE_MESSAGE) { 2252 sb.append("start"); 2253 } else { 2254 sb.append("write"); 2255 } 2256 sb.append(getFieldCountString(expectedCount)); 2257 sb.append(getFieldTypeString(expectedType)); 2258 sb.append(" called with an invalid fieldId: 0x"); 2259 sb.append(Long.toHexString(fieldId)); 2260 sb.append(". The proto field ID might be "); 2261 sb.append((int)fieldId); 2262 sb.append('.'); 2263 throw new IllegalArgumentException(sb.toString()); 2264 } 2265 } 2266 return (int)fieldId; 2267 } 2268 2269 /** 2270 * Return how many bytes an encoded field tag will require. 2271 */ getTagSize(int id)2272 private static int getTagSize(int id) { 2273 return EncodedBuffer.getRawVarint32Size(id << FIELD_ID_SHIFT); 2274 } 2275 2276 /** 2277 * Write an individual field tag by hand. 2278 * 2279 * See <a href="https://developers.google.com/protocol-buffers/docs/encoding">Protobuf 2280 * Encoding</a> for details on the structure of how tags and data are written. 2281 */ writeTag(int id, @WireType int wireType)2282 public void writeTag(int id, @WireType int wireType) { 2283 mBuffer.writeRawVarint32((id << FIELD_ID_SHIFT) | wireType); 2284 } 2285 2286 /** 2287 * Write the header of a WIRE_TYPE_LENGTH_DELIMITED field for one where 2288 * we know the size in advance and do not need to compute and compact. 2289 */ writeKnownLengthHeader(int id, int size)2290 private void writeKnownLengthHeader(int id, int size) { 2291 // Write the tag 2292 writeTag(id, WIRE_TYPE_LENGTH_DELIMITED); 2293 // Size will be compacted later, but we know the size, so write it, 2294 // once for the rawSize and once for the encodedSize. 2295 mBuffer.writeRawFixed32(size); 2296 mBuffer.writeRawFixed32(size); 2297 } 2298 2299 // 2300 // Getting the buffer and compaction 2301 // 2302 2303 /** 2304 * Assert that the compact call has not already occured. 2305 * 2306 * TODO: Will change when we add the OutputStream version of ProtoOutputStream. 2307 */ assertNotCompacted()2308 private void assertNotCompacted() { 2309 if (mCompacted) { 2310 throw new IllegalArgumentException("write called after compact"); 2311 } 2312 } 2313 2314 /** 2315 * Finish the encoding of the data, and return a byte[] with 2316 * the protobuf formatted data. 2317 * 2318 * <p>After this call, do not call any of the write* functions. The 2319 * behavior is undefined. 2320 */ getBytes()2321 public @NonNull byte[] getBytes() { 2322 compactIfNecessary(); 2323 2324 return mBuffer.getBytes(mBuffer.getReadableSize()); 2325 } 2326 2327 /** 2328 * If the buffer hasn't already had the nested object size fields compacted 2329 * and turned into an actual protobuf format, then do so. 2330 */ compactIfNecessary()2331 private void compactIfNecessary() { 2332 if (!mCompacted) { 2333 if (mDepth != 0) { 2334 throw new IllegalArgumentException("Trying to compact with " + mDepth 2335 + " missing calls to endObject"); 2336 } 2337 2338 // The buffer must be compacted. 2339 mBuffer.startEditing(); 2340 final int readableSize = mBuffer.getReadableSize(); 2341 2342 // Cache the sizes of the objects 2343 editEncodedSize(readableSize); 2344 2345 // Re-write the buffer with the sizes as proper varints instead 2346 // of pairs of uint32s. We know this will always fit in the same 2347 // buffer because the pair of uint32s is exactly 8 bytes long, and 2348 // the single varint size will be no more than 5 bytes long. 2349 mBuffer.rewindRead(); 2350 compactSizes(readableSize); 2351 2352 // If there is any data left over that wasn't copied yet, copy it. 2353 if (mCopyBegin < readableSize) { 2354 mBuffer.writeFromThisBuffer(mCopyBegin, readableSize - mCopyBegin); 2355 } 2356 2357 // Set the new readableSize 2358 mBuffer.startEditing(); 2359 2360 // It's not valid to write to this object anymore. The write 2361 // pointers are off, and then some of the data would be compacted 2362 // and some not. 2363 mCompacted = true; 2364 } 2365 } 2366 2367 /** 2368 * First compaction pass. Iterate through the data, and fill in the 2369 * nested object sizes so the next pass can compact them. 2370 */ editEncodedSize(int rawSize)2371 private int editEncodedSize(int rawSize) { 2372 int objectStart = mBuffer.getReadPos(); 2373 int objectEnd = objectStart + rawSize; 2374 int encodedSize = 0; 2375 int tagPos; 2376 2377 while ((tagPos = mBuffer.getReadPos()) < objectEnd) { 2378 int tag = readRawTag(); 2379 encodedSize += EncodedBuffer.getRawVarint32Size(tag); 2380 2381 final int wireType = tag & WIRE_TYPE_MASK; 2382 switch (wireType) { 2383 case WIRE_TYPE_VARINT: 2384 encodedSize++; 2385 while ((mBuffer.readRawByte() & 0x80) != 0) { 2386 encodedSize++; 2387 } 2388 break; 2389 case WIRE_TYPE_FIXED64: 2390 encodedSize += 8; 2391 mBuffer.skipRead(8); 2392 break; 2393 case WIRE_TYPE_LENGTH_DELIMITED: { 2394 // This object is not of a fixed-size type. So we need to figure 2395 // out how big it should be. 2396 final int childRawSize = mBuffer.readRawFixed32(); 2397 final int childEncodedSizePos = mBuffer.getReadPos(); 2398 int childEncodedSize = mBuffer.readRawFixed32(); 2399 if (childRawSize >= 0) { 2400 // We know the size, just skip ahead. 2401 if (childEncodedSize != childRawSize) { 2402 throw new RuntimeException("Pre-computed size where the" 2403 + " precomputed size and the raw size in the buffer" 2404 + " don't match! childRawSize=" + childRawSize 2405 + " childEncodedSize=" + childEncodedSize 2406 + " childEncodedSizePos=" + childEncodedSizePos); 2407 } 2408 mBuffer.skipRead(childRawSize); 2409 } else { 2410 // We need to compute the size. Recurse. 2411 childEncodedSize = editEncodedSize(-childRawSize); 2412 mBuffer.editRawFixed32(childEncodedSizePos, childEncodedSize); 2413 } 2414 encodedSize += EncodedBuffer.getRawVarint32Size(childEncodedSize) 2415 + childEncodedSize; 2416 break; 2417 } 2418 case WIRE_TYPE_START_GROUP: 2419 case WIRE_TYPE_END_GROUP: 2420 throw new RuntimeException("groups not supported at index " + tagPos); 2421 case WIRE_TYPE_FIXED32: 2422 encodedSize += 4; 2423 mBuffer.skipRead(4); 2424 break; 2425 default: 2426 throw new ProtoParseException("editEncodedSize Bad tag tag=0x" 2427 + Integer.toHexString(tag) + " wireType=" + wireType 2428 + " -- " + mBuffer.getDebugString()); 2429 } 2430 } 2431 2432 return encodedSize; 2433 } 2434 2435 /** 2436 * Second compaction pass. Iterate through the data, and copy the data 2437 * forward in the buffer, converting the pairs of uint32s into a single 2438 * unsigned varint of the size. 2439 */ compactSizes(int rawSize)2440 private void compactSizes(int rawSize) { 2441 int objectStart = mBuffer.getReadPos(); 2442 int objectEnd = objectStart + rawSize; 2443 int tagPos; 2444 while ((tagPos = mBuffer.getReadPos()) < objectEnd) { 2445 int tag = readRawTag(); 2446 2447 // For all the non-length-delimited field types, just skip over them, 2448 // and we'll just System.arraycopy it later, either in the case for 2449 // WIRE_TYPE_LENGTH_DELIMITED or at the top of the stack in compactIfNecessary(). 2450 final int wireType = tag & WIRE_TYPE_MASK; 2451 switch (wireType) { 2452 case WIRE_TYPE_VARINT: 2453 while ((mBuffer.readRawByte() & 0x80) != 0) { } 2454 break; 2455 case WIRE_TYPE_FIXED64: 2456 mBuffer.skipRead(8); 2457 break; 2458 case WIRE_TYPE_LENGTH_DELIMITED: { 2459 // Copy everything up to now, including the tag for this field. 2460 mBuffer.writeFromThisBuffer(mCopyBegin, mBuffer.getReadPos() - mCopyBegin); 2461 // Write the new size. 2462 final int childRawSize = mBuffer.readRawFixed32(); 2463 final int childEncodedSize = mBuffer.readRawFixed32(); 2464 mBuffer.writeRawVarint32(childEncodedSize); 2465 // Next time, start copying from here. 2466 mCopyBegin = mBuffer.getReadPos(); 2467 if (childRawSize >= 0) { 2468 // This is raw data, not an object. Skip ahead by the size. 2469 // Recurse into the child 2470 mBuffer.skipRead(childEncodedSize); 2471 } else { 2472 compactSizes(-childRawSize); 2473 } 2474 break; 2475 // TODO: What does regular proto do if the object would be 0 size 2476 // (e.g. if it is all default values). 2477 } 2478 case WIRE_TYPE_START_GROUP: 2479 case WIRE_TYPE_END_GROUP: 2480 throw new RuntimeException("groups not supported at index " + tagPos); 2481 case WIRE_TYPE_FIXED32: 2482 mBuffer.skipRead(4); 2483 break; 2484 default: 2485 throw new ProtoParseException("compactSizes Bad tag tag=0x" 2486 + Integer.toHexString(tag) + " wireType=" + wireType 2487 + " -- " + mBuffer.getDebugString()); 2488 } 2489 } 2490 } 2491 2492 /** 2493 * Write remaining data to the output stream. If there is no output stream, 2494 * this function does nothing. Any currently open objects (i.e. ones that 2495 * have not had {@link #end(long)} called for them will not be written). Whether this 2496 * writes objects that are closed if there are remaining open objects is 2497 * undefined (current implementation does not write it, future ones will). 2498 * For now, can either call {@link #getBytes()} or {@link #flush()}, but not both. 2499 */ flush()2500 public void flush() { 2501 if (mStream == null) { 2502 return; 2503 } 2504 if (mDepth != 0) { 2505 // TODO: The compacting code isn't ready yet to compact unless we're done. 2506 // TODO: Fix that. 2507 return; 2508 } 2509 if (mCompacted) { 2510 // If we're compacted, we already wrote it finished. 2511 return; 2512 } 2513 compactIfNecessary(); 2514 final byte[] data = mBuffer.getBytes(mBuffer.getReadableSize()); 2515 try { 2516 mStream.write(data); 2517 mStream.flush(); 2518 } catch (IOException ex) { 2519 throw new RuntimeException("Error flushing proto to stream", ex); 2520 } 2521 } 2522 2523 /** 2524 * Read a raw tag from the buffer. 2525 */ readRawTag()2526 private int readRawTag() { 2527 if (mBuffer.getReadPos() == mBuffer.getReadableSize()) { 2528 return 0; 2529 } 2530 return (int)mBuffer.readRawUnsigned(); 2531 } 2532 2533 /** 2534 * Dump debugging data about the buffers with the given log tag. 2535 */ dump(@onNull String tag)2536 public void dump(@NonNull String tag) { 2537 Log.d(tag, mBuffer.getDebugString()); 2538 mBuffer.dumpBuffers(tag); 2539 } 2540 } 2541