Home | History | Annotate | Download | only in micro
      1 // Protocol Buffers - Google's data interchange format
      2 // Copyright 2008 Google Inc.  All rights reserved.
      3 // http://code.google.com/p/protobuf/
      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.micro;
     32 
     33 import java.io.OutputStream;
     34 import java.io.IOException;
     35 import java.io.UnsupportedEncodingException;
     36 
     37 /**
     38  * Encodes and writes protocol message fields.
     39  *
     40  * <p>This class contains two kinds of methods:  methods that write specific
     41  * protocol message constructs and field types (e.g. {@link #writeTag} and
     42  * {@link #writeInt32}) and methods that write low-level values (e.g.
     43  * {@link #writeRawVarint32} and {@link #writeRawBytes}).  If you are
     44  * writing encoded protocol messages, you should use the former methods, but if
     45  * you are writing some other format of your own design, use the latter.
     46  *
     47  * <p>This class is totally unsynchronized.
     48  *
     49  * @author kneton (at) google.com Kenton Varda
     50  */
     51 public final class CodedOutputStreamMicro {
     52   private final byte[] buffer;
     53   private final int limit;
     54   private int position;
     55 
     56   private final OutputStream output;
     57 
     58   /**
     59    * The buffer size used in {@link #newInstance(OutputStream)}.
     60    */
     61   public static final int DEFAULT_BUFFER_SIZE = 4096;
     62 
     63   private CodedOutputStreamMicro(final byte[] buffer, final int offset,
     64                             final int length) {
     65     output = null;
     66     this.buffer = buffer;
     67     position = offset;
     68     limit = offset + length;
     69   }
     70 
     71   private CodedOutputStreamMicro(final OutputStream output, final byte[] buffer) {
     72     this.output = output;
     73     this.buffer = buffer;
     74     position = 0;
     75     limit = buffer.length;
     76   }
     77 
     78   /**
     79    * Create a new {@code CodedOutputStream} wrapping the given
     80    * {@code OutputStream}.
     81    */
     82   public static CodedOutputStreamMicro newInstance(final OutputStream output) {
     83     return newInstance(output, DEFAULT_BUFFER_SIZE);
     84   }
     85 
     86   /**
     87    * Create a new {@code CodedOutputStream} wrapping the given
     88    * {@code OutputStream} with a given buffer size.
     89    */
     90   public static CodedOutputStreamMicro newInstance(final OutputStream output,
     91       final int bufferSize) {
     92     return new CodedOutputStreamMicro(output, new byte[bufferSize]);
     93   }
     94 
     95   /**
     96    * Create a new {@code CodedOutputStream} that writes directly to the given
     97    * byte array.  If more bytes are written than fit in the array,
     98    * {@link OutOfSpaceException} will be thrown.  Writing directly to a flat
     99    * array is faster than writing to an {@code OutputStream}.
    100    */
    101   public static CodedOutputStreamMicro newInstance(final byte[] flatArray) {
    102     return newInstance(flatArray, 0, flatArray.length);
    103   }
    104 
    105   /**
    106    * Create a new {@code CodedOutputStream} that writes directly to the given
    107    * byte array slice.  If more bytes are written than fit in the slice,
    108    * {@link OutOfSpaceException} will be thrown.  Writing directly to a flat
    109    * array is faster than writing to an {@code OutputStream}.
    110    */
    111   public static CodedOutputStreamMicro newInstance(final byte[] flatArray,
    112                                               final int offset,
    113                                               final int length) {
    114     return new CodedOutputStreamMicro(flatArray, offset, length);
    115   }
    116 
    117   // -----------------------------------------------------------------
    118 
    119   /** Write a {@code double} field, including tag, to the stream. */
    120   public void writeDouble(final int fieldNumber, final double value)
    121                           throws IOException {
    122     writeTag(fieldNumber, WireFormatMicro.WIRETYPE_FIXED64);
    123     writeDoubleNoTag(value);
    124   }
    125 
    126   /** Write a {@code float} field, including tag, to the stream. */
    127   public void writeFloat(final int fieldNumber, final float value)
    128                          throws IOException {
    129     writeTag(fieldNumber, WireFormatMicro.WIRETYPE_FIXED32);
    130     writeFloatNoTag(value);
    131   }
    132 
    133   /** Write a {@code uint64} field, including tag, to the stream. */
    134   public void writeUInt64(final int fieldNumber, final long value)
    135                           throws IOException {
    136     writeTag(fieldNumber, WireFormatMicro.WIRETYPE_VARINT);
    137     writeUInt64NoTag(value);
    138   }
    139 
    140   /** Write an {@code int64} field, including tag, to the stream. */
    141   public void writeInt64(final int fieldNumber, final long value)
    142                          throws IOException {
    143     writeTag(fieldNumber, WireFormatMicro.WIRETYPE_VARINT);
    144     writeInt64NoTag(value);
    145   }
    146 
    147   /** Write an {@code int32} field, including tag, to the stream. */
    148   public void writeInt32(final int fieldNumber, final int value)
    149                          throws IOException {
    150     writeTag(fieldNumber, WireFormatMicro.WIRETYPE_VARINT);
    151     writeInt32NoTag(value);
    152   }
    153 
    154   /** Write a {@code fixed64} field, including tag, to the stream. */
    155   public void writeFixed64(final int fieldNumber, final long value)
    156                            throws IOException {
    157     writeTag(fieldNumber, WireFormatMicro.WIRETYPE_FIXED64);
    158     writeFixed64NoTag(value);
    159   }
    160 
    161   /** Write a {@code fixed32} field, including tag, to the stream. */
    162   public void writeFixed32(final int fieldNumber, final int value)
    163                            throws IOException {
    164     writeTag(fieldNumber, WireFormatMicro.WIRETYPE_FIXED32);
    165     writeFixed32NoTag(value);
    166   }
    167 
    168   /** Write a {@code bool} field, including tag, to the stream. */
    169   public void writeBool(final int fieldNumber, final boolean value)
    170                         throws IOException {
    171     writeTag(fieldNumber, WireFormatMicro.WIRETYPE_VARINT);
    172     writeBoolNoTag(value);
    173   }
    174 
    175   /** Write a {@code string} field, including tag, to the stream. */
    176   public void writeString(final int fieldNumber, final String value)
    177                           throws IOException {
    178     writeTag(fieldNumber, WireFormatMicro.WIRETYPE_LENGTH_DELIMITED);
    179     writeStringNoTag(value);
    180   }
    181 
    182   /** Write a {@code group} field, including tag, to the stream. */
    183   public void writeGroup(final int fieldNumber, final MessageMicro value)
    184                          throws IOException {
    185     writeTag(fieldNumber, WireFormatMicro.WIRETYPE_START_GROUP);
    186     writeGroupNoTag(value);
    187     writeTag(fieldNumber, WireFormatMicro.WIRETYPE_END_GROUP);
    188   }
    189 
    190   /** Write an embedded message field, including tag, to the stream. */
    191   public void writeMessage(final int fieldNumber, final MessageMicro value)
    192                            throws IOException {
    193     writeTag(fieldNumber, WireFormatMicro.WIRETYPE_LENGTH_DELIMITED);
    194     writeMessageNoTag(value);
    195   }
    196 
    197   /** Write a {@code bytes} field, including tag, to the stream. */
    198   public void writeBytes(final int fieldNumber, final ByteStringMicro value)
    199                          throws IOException {
    200     writeTag(fieldNumber, WireFormatMicro.WIRETYPE_LENGTH_DELIMITED);
    201     writeBytesNoTag(value);
    202   }
    203 
    204   /** Write a {@code byte} field, including tag, to the stream. */
    205   public void writeByteArray(final int fieldNumber, final byte[] value)
    206                          throws IOException {
    207     writeTag(fieldNumber, WireFormatMicro.WIRETYPE_LENGTH_DELIMITED);
    208     writeByteArrayNoTag(value);
    209   }
    210 
    211 
    212   /** Write a {@code uint32} field, including tag, to the stream. */
    213   public void writeUInt32(final int fieldNumber, final int value)
    214                           throws IOException {
    215     writeTag(fieldNumber, WireFormatMicro.WIRETYPE_VARINT);
    216     writeUInt32NoTag(value);
    217   }
    218 
    219   /**
    220    * Write an enum field, including tag, to the stream.  Caller is responsible
    221    * for converting the enum value to its numeric value.
    222    */
    223   public void writeEnum(final int fieldNumber, final int value)
    224                         throws IOException {
    225     writeTag(fieldNumber, WireFormatMicro.WIRETYPE_VARINT);
    226     writeEnumNoTag(value);
    227   }
    228 
    229   /** Write an {@code sfixed32} field, including tag, to the stream. */
    230   public void writeSFixed32(final int fieldNumber, final int value)
    231                             throws IOException {
    232     writeTag(fieldNumber, WireFormatMicro.WIRETYPE_FIXED32);
    233     writeSFixed32NoTag(value);
    234   }
    235 
    236   /** Write an {@code sfixed64} field, including tag, to the stream. */
    237   public void writeSFixed64(final int fieldNumber, final long value)
    238                             throws IOException {
    239     writeTag(fieldNumber, WireFormatMicro.WIRETYPE_FIXED64);
    240     writeSFixed64NoTag(value);
    241   }
    242 
    243   /** Write an {@code sint32} field, including tag, to the stream. */
    244   public void writeSInt32(final int fieldNumber, final int value)
    245                           throws IOException {
    246     writeTag(fieldNumber, WireFormatMicro.WIRETYPE_VARINT);
    247     writeSInt32NoTag(value);
    248   }
    249 
    250   /** Write an {@code sint64} field, including tag, to the stream. */
    251   public void writeSInt64(final int fieldNumber, final long value)
    252                           throws IOException {
    253     writeTag(fieldNumber, WireFormatMicro.WIRETYPE_VARINT);
    254     writeSInt64NoTag(value);
    255   }
    256 
    257   /**
    258    * Write a MessageSet extension field to the stream.  For historical reasons,
    259    * the wire format differs from normal fields.
    260    */
    261 //  public void writeMessageSetExtension(final int fieldNumber,
    262 //                                       final MessageMicro value)
    263 //                                       throws IOException {
    264 //    writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_START_GROUP);
    265 //    writeUInt32(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber);
    266 //    writeMessage(WireFormatMicro.MESSAGE_SET_MESSAGE, value);
    267 //    writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_END_GROUP);
    268 //  }
    269 
    270   /**
    271    * Write an unparsed MessageSet extension field to the stream.  For
    272    * historical reasons, the wire format differs from normal fields.
    273    */
    274 //  public void writeRawMessageSetExtension(final int fieldNumber,
    275 //                                          final ByteStringMicro value)
    276 //                                          throws IOException {
    277 //    writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_START_GROUP);
    278 //    writeUInt32(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber);
    279 //    writeBytes(WireFormatMicro.MESSAGE_SET_MESSAGE, value);
    280 //    writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_END_GROUP);
    281 //  }
    282 
    283   // -----------------------------------------------------------------
    284 
    285   /** Write a {@code double} field to the stream. */
    286   public void writeDoubleNoTag(final double value) throws IOException {
    287     writeRawLittleEndian64(Double.doubleToLongBits(value));
    288   }
    289 
    290   /** Write a {@code float} field to the stream. */
    291   public void writeFloatNoTag(final float value) throws IOException {
    292     writeRawLittleEndian32(Float.floatToIntBits(value));
    293   }
    294 
    295   /** Write a {@code uint64} field to the stream. */
    296   public void writeUInt64NoTag(final long value) throws IOException {
    297     writeRawVarint64(value);
    298   }
    299 
    300   /** Write an {@code int64} field to the stream. */
    301   public void writeInt64NoTag(final long value) throws IOException {
    302     writeRawVarint64(value);
    303   }
    304 
    305   /** Write an {@code int32} field to the stream. */
    306   public void writeInt32NoTag(final int value) throws IOException {
    307     if (value >= 0) {
    308       writeRawVarint32(value);
    309     } else {
    310       // Must sign-extend.
    311       writeRawVarint64(value);
    312     }
    313   }
    314 
    315   /** Write a {@code fixed64} field to the stream. */
    316   public void writeFixed64NoTag(final long value) throws IOException {
    317     writeRawLittleEndian64(value);
    318   }
    319 
    320   /** Write a {@code fixed32} field to the stream. */
    321   public void writeFixed32NoTag(final int value) throws IOException {
    322     writeRawLittleEndian32(value);
    323   }
    324 
    325   /** Write a {@code bool} field to the stream. */
    326   public void writeBoolNoTag(final boolean value) throws IOException {
    327     writeRawByte(value ? 1 : 0);
    328   }
    329 
    330   /** Write a {@code string} field to the stream. */
    331   public void writeStringNoTag(final String value) throws IOException {
    332     // Unfortunately there does not appear to be any way to tell Java to encode
    333     // UTF-8 directly into our buffer, so we have to let it create its own byte
    334     // array and then copy.
    335     final byte[] bytes = value.getBytes("UTF-8");
    336     writeRawVarint32(bytes.length);
    337     writeRawBytes(bytes);
    338   }
    339 
    340   /** Write a {@code group} field to the stream. */
    341   public void writeGroupNoTag(final MessageMicro value) throws IOException {
    342     value.writeTo(this);
    343   }
    344 
    345   /** Write an embedded message field to the stream. */
    346   public void writeMessageNoTag(final MessageMicro value) throws IOException {
    347     writeRawVarint32(value.getCachedSize());
    348     value.writeTo(this);
    349   }
    350 
    351   /** Write a {@code bytes} field to the stream. */
    352   public void writeBytesNoTag(final ByteStringMicro value) throws IOException {
    353     final byte[] bytes = value.toByteArray();
    354     writeRawVarint32(bytes.length);
    355     writeRawBytes(bytes);
    356   }
    357 
    358   /** Write a {@code byte[]} field to the stream. */
    359   public void writeByteArrayNoTag(final byte [] value) throws IOException {
    360     writeRawVarint32(value.length);
    361     writeRawBytes(value);
    362   }
    363 
    364   /** Write a {@code uint32} field to the stream. */
    365   public void writeUInt32NoTag(final int value) throws IOException {
    366     writeRawVarint32(value);
    367   }
    368 
    369   /**
    370    * Write an enum field to the stream.  Caller is responsible
    371    * for converting the enum value to its numeric value.
    372    */
    373   public void writeEnumNoTag(final int value) throws IOException {
    374     writeRawVarint32(value);
    375   }
    376 
    377   /** Write an {@code sfixed32} field to the stream. */
    378   public void writeSFixed32NoTag(final int value) throws IOException {
    379     writeRawLittleEndian32(value);
    380   }
    381 
    382   /** Write an {@code sfixed64} field to the stream. */
    383   public void writeSFixed64NoTag(final long value) throws IOException {
    384     writeRawLittleEndian64(value);
    385   }
    386 
    387   /** Write an {@code sint32} field to the stream. */
    388   public void writeSInt32NoTag(final int value) throws IOException {
    389     writeRawVarint32(encodeZigZag32(value));
    390   }
    391 
    392   /** Write an {@code sint64} field to the stream. */
    393   public void writeSInt64NoTag(final long value) throws IOException {
    394     writeRawVarint64(encodeZigZag64(value));
    395   }
    396 
    397   // =================================================================
    398 
    399   /**
    400    * Compute the number of bytes that would be needed to encode a
    401    * {@code double} field, including tag.
    402    */
    403   public static int computeDoubleSize(final int fieldNumber,
    404                                       final double value) {
    405     return computeTagSize(fieldNumber) + computeDoubleSizeNoTag(value);
    406   }
    407 
    408   /**
    409    * Compute the number of bytes that would be needed to encode a
    410    * {@code float} field, including tag.
    411    */
    412   public static int computeFloatSize(final int fieldNumber, final float value) {
    413     return computeTagSize(fieldNumber) + computeFloatSizeNoTag(value);
    414   }
    415 
    416   /**
    417    * Compute the number of bytes that would be needed to encode a
    418    * {@code uint64} field, including tag.
    419    */
    420   public static int computeUInt64Size(final int fieldNumber, final long value) {
    421     return computeTagSize(fieldNumber) + computeUInt64SizeNoTag(value);
    422   }
    423 
    424   /**
    425    * Compute the number of bytes that would be needed to encode an
    426    * {@code int64} field, including tag.
    427    */
    428   public static int computeInt64Size(final int fieldNumber, final long value) {
    429     return computeTagSize(fieldNumber) + computeInt64SizeNoTag(value);
    430   }
    431 
    432   /**
    433    * Compute the number of bytes that would be needed to encode an
    434    * {@code int32} field, including tag.
    435    */
    436   public static int computeInt32Size(final int fieldNumber, final int value) {
    437     return computeTagSize(fieldNumber) + computeInt32SizeNoTag(value);
    438   }
    439 
    440   /**
    441    * Compute the number of bytes that would be needed to encode a
    442    * {@code fixed64} field, including tag.
    443    */
    444   public static int computeFixed64Size(final int fieldNumber,
    445                                        final long value) {
    446     return computeTagSize(fieldNumber) + computeFixed64SizeNoTag(value);
    447   }
    448 
    449   /**
    450    * Compute the number of bytes that would be needed to encode a
    451    * {@code fixed32} field, including tag.
    452    */
    453   public static int computeFixed32Size(final int fieldNumber,
    454                                        final int value) {
    455     return computeTagSize(fieldNumber) + computeFixed32SizeNoTag(value);
    456   }
    457 
    458   /**
    459    * Compute the number of bytes that would be needed to encode a
    460    * {@code bool} field, including tag.
    461    */
    462   public static int computeBoolSize(final int fieldNumber,
    463                                     final boolean value) {
    464     return computeTagSize(fieldNumber) + computeBoolSizeNoTag(value);
    465   }
    466 
    467   /**
    468    * Compute the number of bytes that would be needed to encode a
    469    * {@code string} field, including tag.
    470    */
    471   public static int computeStringSize(final int fieldNumber,
    472                                       final String value) {
    473     return computeTagSize(fieldNumber) + computeStringSizeNoTag(value);
    474   }
    475 
    476   /**
    477    * Compute the number of bytes that would be needed to encode a
    478    * {@code group} field, including tag.
    479    */
    480   public static int computeGroupSize(final int fieldNumber,
    481                                      final MessageMicro value) {
    482     return computeTagSize(fieldNumber) * 2 + computeGroupSizeNoTag(value);
    483   }
    484 
    485   /**
    486    * Compute the number of bytes that would be needed to encode an
    487    * embedded message field, including tag.
    488    */
    489   public static int computeMessageSize(final int fieldNumber,
    490                                        final MessageMicro value) {
    491     return computeTagSize(fieldNumber) + computeMessageSizeNoTag(value);
    492   }
    493 
    494   /**
    495    * Compute the number of bytes that would be needed to encode a
    496    * {@code bytes} field, including tag.
    497    */
    498   public static int computeBytesSize(final int fieldNumber,
    499                                      final ByteStringMicro value) {
    500     return computeTagSize(fieldNumber) + computeBytesSizeNoTag(value);
    501   }
    502 
    503   /**
    504    * Compute the number of bytes that would be needed to encode a
    505    * {@code byte[]} field, including tag.
    506    */
    507   public static int computeByteArraySize(final int fieldNumber,
    508                                      final byte[] value) {
    509     return computeTagSize(fieldNumber) + computeByteArraySizeNoTag(value);
    510   }
    511 
    512   /**
    513    * Compute the number of bytes that would be needed to encode a
    514    * {@code uint32} field, including tag.
    515    */
    516   public static int computeUInt32Size(final int fieldNumber, final int value) {
    517     return computeTagSize(fieldNumber) + computeUInt32SizeNoTag(value);
    518   }
    519 
    520   /**
    521    * Compute the number of bytes that would be needed to encode an
    522    * enum field, including tag.  Caller is responsible for converting the
    523    * enum value to its numeric value.
    524    */
    525   public static int computeEnumSize(final int fieldNumber, final int value) {
    526     return computeTagSize(fieldNumber) + computeEnumSizeNoTag(value);
    527   }
    528 
    529   /**
    530    * Compute the number of bytes that would be needed to encode an
    531    * {@code sfixed32} field, including tag.
    532    */
    533   public static int computeSFixed32Size(final int fieldNumber,
    534                                         final int value) {
    535     return computeTagSize(fieldNumber) + computeSFixed32SizeNoTag(value);
    536   }
    537 
    538   /**
    539    * Compute the number of bytes that would be needed to encode an
    540    * {@code sfixed64} field, including tag.
    541    */
    542   public static int computeSFixed64Size(final int fieldNumber,
    543                                         final long value) {
    544     return computeTagSize(fieldNumber) + computeSFixed64SizeNoTag(value);
    545   }
    546 
    547   /**
    548    * Compute the number of bytes that would be needed to encode an
    549    * {@code sint32} field, including tag.
    550    */
    551   public static int computeSInt32Size(final int fieldNumber, final int value) {
    552     return computeTagSize(fieldNumber) + computeSInt32SizeNoTag(value);
    553   }
    554 
    555   /**
    556    * Compute the number of bytes that would be needed to encode an
    557    * {@code sint64} field, including tag.
    558    */
    559   public static int computeSInt64Size(final int fieldNumber, final long value) {
    560     return computeTagSize(fieldNumber) + computeSInt64SizeNoTag(value);
    561   }
    562 
    563   /**
    564    * Compute the number of bytes that would be needed to encode a
    565    * MessageSet extension to the stream.  For historical reasons,
    566    * the wire format differs from normal fields.
    567    */
    568 //  public static int computeMessageSetExtensionSize(
    569 //      final int fieldNumber, final MessageMicro value) {
    570 //    return computeTagSize(WireFormatMicro.MESSAGE_SET_ITEM) * 2 +
    571 //           computeUInt32Size(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber) +
    572 //           computeMessageSize(WireFormatMicro.MESSAGE_SET_MESSAGE, value);
    573 //  }
    574 
    575   /**
    576    * Compute the number of bytes that would be needed to encode an
    577    * unparsed MessageSet extension field to the stream.  For
    578    * historical reasons, the wire format differs from normal fields.
    579    */
    580 //  public static int computeRawMessageSetExtensionSize(
    581 //      final int fieldNumber, final ByteStringMicro value) {
    582 //    return computeTagSize(WireFormatMicro.MESSAGE_SET_ITEM) * 2 +
    583 //           computeUInt32Size(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber) +
    584 //           computeBytesSize(WireFormatMicro.MESSAGE_SET_MESSAGE, value);
    585 //  }
    586 
    587   // -----------------------------------------------------------------
    588 
    589   /**
    590    * Compute the number of bytes that would be needed to encode a
    591    * {@code double} field, including tag.
    592    */
    593   public static int computeDoubleSizeNoTag(final double value) {
    594     return LITTLE_ENDIAN_64_SIZE;
    595   }
    596 
    597   /**
    598    * Compute the number of bytes that would be needed to encode a
    599    * {@code float} field, including tag.
    600    */
    601   public static int computeFloatSizeNoTag(final float value) {
    602     return LITTLE_ENDIAN_32_SIZE;
    603   }
    604 
    605   /**
    606    * Compute the number of bytes that would be needed to encode a
    607    * {@code uint64} field, including tag.
    608    */
    609   public static int computeUInt64SizeNoTag(final long value) {
    610     return computeRawVarint64Size(value);
    611   }
    612 
    613   /**
    614    * Compute the number of bytes that would be needed to encode an
    615    * {@code int64} field, including tag.
    616    */
    617   public static int computeInt64SizeNoTag(final long value) {
    618     return computeRawVarint64Size(value);
    619   }
    620 
    621   /**
    622    * Compute the number of bytes that would be needed to encode an
    623    * {@code int32} field, including tag.
    624    */
    625   public static int computeInt32SizeNoTag(final int value) {
    626     if (value >= 0) {
    627       return computeRawVarint32Size(value);
    628     } else {
    629       // Must sign-extend.
    630       return 10;
    631     }
    632   }
    633 
    634   /**
    635    * Compute the number of bytes that would be needed to encode a
    636    * {@code fixed64} field.
    637    */
    638   public static int computeFixed64SizeNoTag(final long value) {
    639     return LITTLE_ENDIAN_64_SIZE;
    640   }
    641 
    642   /**
    643    * Compute the number of bytes that would be needed to encode a
    644    * {@code fixed32} field.
    645    */
    646   public static int computeFixed32SizeNoTag(final int value) {
    647     return LITTLE_ENDIAN_32_SIZE;
    648   }
    649 
    650   /**
    651    * Compute the number of bytes that would be needed to encode a
    652    * {@code bool} field.
    653    */
    654   public static int computeBoolSizeNoTag(final boolean value) {
    655     return 1;
    656   }
    657 
    658   /**
    659    * Compute the number of bytes that would be needed to encode a
    660    * {@code string} field.
    661    */
    662   public static int computeStringSizeNoTag(final String value) {
    663     try {
    664       final byte[] bytes = value.getBytes("UTF-8");
    665       return computeRawVarint32Size(bytes.length) +
    666              bytes.length;
    667     } catch (UnsupportedEncodingException e) {
    668       throw new RuntimeException("UTF-8 not supported.");
    669     }
    670   }
    671 
    672   /**
    673    * Compute the number of bytes that would be needed to encode a
    674    * {@code group} field.
    675    */
    676   public static int computeGroupSizeNoTag(final MessageMicro value) {
    677     return value.getSerializedSize();
    678   }
    679 
    680   /**
    681    * Compute the number of bytes that would be needed to encode an embedded
    682    * message field.
    683    */
    684   public static int computeMessageSizeNoTag(final MessageMicro value) {
    685     final int size = value.getSerializedSize();
    686     return computeRawVarint32Size(size) + size;
    687   }
    688 
    689   /**
    690    * Compute the number of bytes that would be needed to encode a
    691    * {@code bytes} field.
    692    */
    693   public static int computeBytesSizeNoTag(final ByteStringMicro value) {
    694     return computeRawVarint32Size(value.size()) + value.size();
    695   }
    696 
    697   /**
    698    * Compute the number of bytes that would be needed to encode a
    699    * {@code byte[]} field.
    700    */
    701   public static int computeByteArraySizeNoTag(final byte[] value) {
    702     return computeRawVarint32Size(value.length) + value.length;
    703   }
    704 
    705   /**
    706    * Compute the number of bytes that would be needed to encode a
    707    * {@code uint32} field.
    708    */
    709   public static int computeUInt32SizeNoTag(final int value) {
    710     return computeRawVarint32Size(value);
    711   }
    712 
    713   /**
    714    * Compute the number of bytes that would be needed to encode an enum field.
    715    * Caller is responsible for converting the enum value to its numeric value.
    716    */
    717   public static int computeEnumSizeNoTag(final int value) {
    718     return computeRawVarint32Size(value);
    719   }
    720 
    721   /**
    722    * Compute the number of bytes that would be needed to encode an
    723    * {@code sfixed32} field.
    724    */
    725   public static int computeSFixed32SizeNoTag(final int value) {
    726     return LITTLE_ENDIAN_32_SIZE;
    727   }
    728 
    729   /**
    730    * Compute the number of bytes that would be needed to encode an
    731    * {@code sfixed64} field.
    732    */
    733   public static int computeSFixed64SizeNoTag(final long value) {
    734     return LITTLE_ENDIAN_64_SIZE;
    735   }
    736 
    737   /**
    738    * Compute the number of bytes that would be needed to encode an
    739    * {@code sint32} field.
    740    */
    741   public static int computeSInt32SizeNoTag(final int value) {
    742     return computeRawVarint32Size(encodeZigZag32(value));
    743   }
    744 
    745   /**
    746    * Compute the number of bytes that would be needed to encode an
    747    * {@code sint64} field.
    748    */
    749   public static int computeSInt64SizeNoTag(final long value) {
    750     return computeRawVarint64Size(encodeZigZag64(value));
    751   }
    752 
    753   // =================================================================
    754 
    755   /**
    756    * Internal helper that writes the current buffer to the output. The
    757    * buffer position is reset to its initial value when this returns.
    758    */
    759   private void refreshBuffer() throws IOException {
    760     if (output == null) {
    761       // We're writing to a single buffer.
    762       throw new OutOfSpaceException();
    763     }
    764 
    765     // Since we have an output stream, this is our buffer
    766     // and buffer offset == 0
    767     output.write(buffer, 0, position);
    768     position = 0;
    769   }
    770 
    771   /**
    772    * Flushes the stream and forces any buffered bytes to be written.  This
    773    * does not flush the underlying OutputStream.
    774    */
    775   public void flush() throws IOException {
    776     if (output != null) {
    777       refreshBuffer();
    778     }
    779   }
    780 
    781   /**
    782    * If writing to a flat array, return the space left in the array.
    783    * Otherwise, throws {@code UnsupportedOperationException}.
    784    */
    785   public int spaceLeft() {
    786     if (output == null) {
    787       return limit - position;
    788     } else {
    789       throw new UnsupportedOperationException(
    790         "spaceLeft() can only be called on CodedOutputStreams that are " +
    791         "writing to a flat array.");
    792     }
    793   }
    794 
    795   /**
    796    * Verifies that {@link #spaceLeft()} returns zero.  It's common to create
    797    * a byte array that is exactly big enough to hold a message, then write to
    798    * it with a {@code CodedOutputStream}.  Calling {@code checkNoSpaceLeft()}
    799    * after writing verifies that the message was actually as big as expected,
    800    * which can help catch bugs.
    801    */
    802   public void checkNoSpaceLeft() {
    803     if (spaceLeft() != 0) {
    804       throw new IllegalStateException(
    805         "Did not write as much data as expected.");
    806     }
    807   }
    808 
    809   /**
    810    * If you create a CodedOutputStream around a simple flat array, you must
    811    * not attempt to write more bytes than the array has space.  Otherwise,
    812    * this exception will be thrown.
    813    */
    814   public static class OutOfSpaceException extends IOException {
    815     private static final long serialVersionUID = -6947486886997889499L;
    816 
    817     OutOfSpaceException() {
    818       super("CodedOutputStream was writing to a flat byte array and ran " +
    819             "out of space.");
    820     }
    821   }
    822 
    823   /** Write a single byte. */
    824   public void writeRawByte(final byte value) throws IOException {
    825     if (position == limit) {
    826       refreshBuffer();
    827     }
    828 
    829     buffer[position++] = value;
    830   }
    831 
    832   /** Write a single byte, represented by an integer value. */
    833   public void writeRawByte(final int value) throws IOException {
    834     writeRawByte((byte) value);
    835   }
    836 
    837   /** Write an array of bytes. */
    838   public void writeRawBytes(final byte[] value) throws IOException {
    839     writeRawBytes(value, 0, value.length);
    840   }
    841 
    842   /** Write part of an array of bytes. */
    843   public void writeRawBytes(final byte[] value, int offset, int length)
    844                             throws IOException {
    845     if (limit - position >= length) {
    846       // We have room in the current buffer.
    847       System.arraycopy(value, offset, buffer, position, length);
    848       position += length;
    849     } else {
    850       // Write extends past current buffer.  Fill the rest of this buffer and
    851       // flush.
    852       final int bytesWritten = limit - position;
    853       System.arraycopy(value, offset, buffer, position, bytesWritten);
    854       offset += bytesWritten;
    855       length -= bytesWritten;
    856       position = limit;
    857       refreshBuffer();
    858 
    859       // Now deal with the rest.
    860       // Since we have an output stream, this is our buffer
    861       // and buffer offset == 0
    862       if (length <= limit) {
    863         // Fits in new buffer.
    864         System.arraycopy(value, offset, buffer, 0, length);
    865         position = length;
    866       } else {
    867         // Write is very big.  Let's do it all at once.
    868         output.write(value, offset, length);
    869       }
    870     }
    871   }
    872 
    873   /** Encode and write a tag. */
    874   public void writeTag(final int fieldNumber, final int wireType)
    875                        throws IOException {
    876     writeRawVarint32(WireFormatMicro.makeTag(fieldNumber, wireType));
    877   }
    878 
    879   /** Compute the number of bytes that would be needed to encode a tag. */
    880   public static int computeTagSize(final int fieldNumber) {
    881     return computeRawVarint32Size(WireFormatMicro.makeTag(fieldNumber, 0));
    882   }
    883 
    884   /**
    885    * Encode and write a varint.  {@code value} is treated as
    886    * unsigned, so it won't be sign-extended if negative.
    887    */
    888   public void writeRawVarint32(int value) throws IOException {
    889     while (true) {
    890       if ((value & ~0x7F) == 0) {
    891         writeRawByte(value);
    892         return;
    893       } else {
    894         writeRawByte((value & 0x7F) | 0x80);
    895         value >>>= 7;
    896       }
    897     }
    898   }
    899 
    900   /**
    901    * Compute the number of bytes that would be needed to encode a varint.
    902    * {@code value} is treated as unsigned, so it won't be sign-extended if
    903    * negative.
    904    */
    905   public static int computeRawVarint32Size(final int value) {
    906     if ((value & (0xffffffff <<  7)) == 0) return 1;
    907     if ((value & (0xffffffff << 14)) == 0) return 2;
    908     if ((value & (0xffffffff << 21)) == 0) return 3;
    909     if ((value & (0xffffffff << 28)) == 0) return 4;
    910     return 5;
    911   }
    912 
    913   /** Encode and write a varint. */
    914   public void writeRawVarint64(long value) throws IOException {
    915     while (true) {
    916       if ((value & ~0x7FL) == 0) {
    917         writeRawByte((int)value);
    918         return;
    919       } else {
    920         writeRawByte(((int)value & 0x7F) | 0x80);
    921         value >>>= 7;
    922       }
    923     }
    924   }
    925 
    926   /** Compute the number of bytes that would be needed to encode a varint. */
    927   public static int computeRawVarint64Size(final long value) {
    928     if ((value & (0xffffffffffffffffL <<  7)) == 0) return 1;
    929     if ((value & (0xffffffffffffffffL << 14)) == 0) return 2;
    930     if ((value & (0xffffffffffffffffL << 21)) == 0) return 3;
    931     if ((value & (0xffffffffffffffffL << 28)) == 0) return 4;
    932     if ((value & (0xffffffffffffffffL << 35)) == 0) return 5;
    933     if ((value & (0xffffffffffffffffL << 42)) == 0) return 6;
    934     if ((value & (0xffffffffffffffffL << 49)) == 0) return 7;
    935     if ((value & (0xffffffffffffffffL << 56)) == 0) return 8;
    936     if ((value & (0xffffffffffffffffL << 63)) == 0) return 9;
    937     return 10;
    938   }
    939 
    940   /** Write a little-endian 32-bit integer. */
    941   public void writeRawLittleEndian32(final int value) throws IOException {
    942     writeRawByte((value      ) & 0xFF);
    943     writeRawByte((value >>  8) & 0xFF);
    944     writeRawByte((value >> 16) & 0xFF);
    945     writeRawByte((value >> 24) & 0xFF);
    946   }
    947 
    948   public static final int LITTLE_ENDIAN_32_SIZE = 4;
    949 
    950   /** Write a little-endian 64-bit integer. */
    951   public void writeRawLittleEndian64(final long value) throws IOException {
    952     writeRawByte((int)(value      ) & 0xFF);
    953     writeRawByte((int)(value >>  8) & 0xFF);
    954     writeRawByte((int)(value >> 16) & 0xFF);
    955     writeRawByte((int)(value >> 24) & 0xFF);
    956     writeRawByte((int)(value >> 32) & 0xFF);
    957     writeRawByte((int)(value >> 40) & 0xFF);
    958     writeRawByte((int)(value >> 48) & 0xFF);
    959     writeRawByte((int)(value >> 56) & 0xFF);
    960   }
    961 
    962   public static final int LITTLE_ENDIAN_64_SIZE = 8;
    963 
    964   /**
    965    * Encode a ZigZag-encoded 32-bit value.  ZigZag encodes signed integers
    966    * into values that can be efficiently encoded with varint.  (Otherwise,
    967    * negative values must be sign-extended to 64 bits to be varint encoded,
    968    * thus always taking 10 bytes on the wire.)
    969    *
    970    * @param n A signed 32-bit integer.
    971    * @return An unsigned 32-bit integer, stored in a signed int because
    972    *         Java has no explicit unsigned support.
    973    */
    974   public static int encodeZigZag32(final int n) {
    975     // Note:  the right-shift must be arithmetic
    976     return (n << 1) ^ (n >> 31);
    977   }
    978 
    979   /**
    980    * Encode a ZigZag-encoded 64-bit value.  ZigZag encodes signed integers
    981    * into values that can be efficiently encoded with varint.  (Otherwise,
    982    * negative values must be sign-extended to 64 bits to be varint encoded,
    983    * thus always taking 10 bytes on the wire.)
    984    *
    985    * @param n A signed 64-bit integer.
    986    * @return An unsigned 64-bit integer, stored in a signed int because
    987    *         Java has no explicit unsigned support.
    988    */
    989   public static long encodeZigZag64(final long n) {
    990     // Note:  the right-shift must be arithmetic
    991     return (n << 1) ^ (n >> 63);
    992   }
    993 }
    994