CodedOutputStreamMicro.java revision ede38fe9b9f93888e6e41afc7abb09525f44da95
1cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com// Protocol Buffers - Google's data interchange format
2cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com// Copyright 2008 Google Inc.  All rights reserved.
3cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com// http://code.google.com/p/protobuf/
4cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com//
5cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com// Redistribution and use in source and binary forms, with or without
6cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com// modification, are permitted provided that the following conditions are
7cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com// met:
8cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com//
9cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com//     * Redistributions of source code must retain the above copyright
108cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com// notice, this list of conditions and the following disclaimer.
118cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com//     * Redistributions in binary form must reproduce the above
128cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com// copyright notice, this list of conditions and the following disclaimer
138cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com// in the documentation and/or other materials provided with the
148cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com// distribution.
158cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com//     * Neither the name of Google Inc. nor the names of its
168cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com// contributors may be used to endorse or promote products derived from
178cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com// this software without specific prior written permission.
188cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com//
198cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
208cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
218cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
228cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
238cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
248cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
258cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
268cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
278cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
288cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
298cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
308cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
318cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.compackage com.google.protobuf.micro;
328cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
338cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comimport java.io.OutputStream;
348cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comimport java.io.IOException;
358cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.comimport java.io.UnsupportedEncodingException;
368cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
378cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com/**
388cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * Encodes and writes protocol message fields.
398cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com *
408cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * <p>This class contains two kinds of methods:  methods that write specific
418cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * protocol message constructs and field types (e.g. {@link #writeTag} and
428cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * {@link #writeInt32}) and methods that write low-level values (e.g.
438cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * {@link #writeRawVarint32} and {@link #writeRawBytes}).  If you are
448cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * writing encoded protocol messages, you should use the former methods, but if
458cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * you are writing some other format of your own design, use the latter.
468cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com *
478cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * <p>This class is totally unsynchronized.
488cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com *
498cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com * @author kneton@google.com Kenton Varda
508cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com */
518cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.compublic final class CodedOutputStreamMicro {
528cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  private final byte[] buffer;
538cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  private final int limit;
548cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  private int position;
558cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
568cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  private final OutputStream output;
578cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
588cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /**
598cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * The buffer size used in {@link #newInstance(OutputStream)}.
608cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   */
618cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public static final int DEFAULT_BUFFER_SIZE = 4096;
628cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
638cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  private CodedOutputStreamMicro(final byte[] buffer, final int offset,
648cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                            final int length) {
658cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    output = null;
668cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    this.buffer = buffer;
678cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    position = offset;
688cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    limit = offset + length;
698cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
708cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
718cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  private CodedOutputStreamMicro(final OutputStream output, final byte[] buffer) {
728cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    this.output = output;
738cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    this.buffer = buffer;
748cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    position = 0;
758cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    limit = buffer.length;
768cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
778cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
788cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /**
798cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * Create a new {@code CodedOutputStream} wrapping the given
808cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * {@code OutputStream}.
818cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   */
828cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public static CodedOutputStreamMicro newInstance(final OutputStream output) {
838cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    return newInstance(output, DEFAULT_BUFFER_SIZE);
848cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
858cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
868cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /**
878cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * Create a new {@code CodedOutputStream} wrapping the given
888cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * {@code OutputStream} with a given buffer size.
898cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   */
908cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public static CodedOutputStreamMicro newInstance(final OutputStream output,
918cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com      final int bufferSize) {
928cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    return new CodedOutputStreamMicro(output, new byte[bufferSize]);
938cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
948cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
958cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /**
968cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * Create a new {@code CodedOutputStream} that writes directly to the given
978cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * byte array.  If more bytes are written than fit in the array,
988cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * {@link OutOfSpaceException} will be thrown.  Writing directly to a flat
998cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * array is faster than writing to an {@code OutputStream}.
1008cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   */
1018cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public static CodedOutputStreamMicro newInstance(final byte[] flatArray) {
1028cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    return newInstance(flatArray, 0, flatArray.length);
1038cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
1048cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
1058cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /**
1068cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * Create a new {@code CodedOutputStream} that writes directly to the given
1078cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * byte array slice.  If more bytes are written than fit in the slice,
1088cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * {@link OutOfSpaceException} will be thrown.  Writing directly to a flat
1098cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * array is faster than writing to an {@code OutputStream}.
1108cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   */
1118cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public static CodedOutputStreamMicro newInstance(final byte[] flatArray,
1128cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                                              final int offset,
1138cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                                              final int length) {
1148cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    return new CodedOutputStreamMicro(flatArray, offset, length);
1158cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
1168cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
1178cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  // -----------------------------------------------------------------
1188cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
1198cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /** Write a {@code double} field, including tag, to the stream. */
1208cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public void writeDouble(final int fieldNumber, final double value)
1218cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                          throws IOException {
1228cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeTag(fieldNumber, WireFormatMicro.WIRETYPE_FIXED64);
1238cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeDoubleNoTag(value);
1248cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
1258cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
1268cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /** Write a {@code float} field, including tag, to the stream. */
1278cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public void writeFloat(final int fieldNumber, final float value)
1288cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                         throws IOException {
1298cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeTag(fieldNumber, WireFormatMicro.WIRETYPE_FIXED32);
1308cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeFloatNoTag(value);
1318cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
1328cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
1338cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /** Write a {@code uint64} field, including tag, to the stream. */
1348cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public void writeUInt64(final int fieldNumber, final long value)
1358cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                          throws IOException {
1368cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeTag(fieldNumber, WireFormatMicro.WIRETYPE_VARINT);
1378cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeUInt64NoTag(value);
1388cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
1398cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
1408cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /** Write an {@code int64} field, including tag, to the stream. */
1418cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public void writeInt64(final int fieldNumber, final long value)
1428cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                         throws IOException {
1438cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeTag(fieldNumber, WireFormatMicro.WIRETYPE_VARINT);
1448cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeInt64NoTag(value);
1458cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
1468cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
1478cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /** Write an {@code int32} field, including tag, to the stream. */
1488cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public void writeInt32(final int fieldNumber, final int value)
1498cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                         throws IOException {
1508cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeTag(fieldNumber, WireFormatMicro.WIRETYPE_VARINT);
1518cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeInt32NoTag(value);
1528cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
1538cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
1548cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /** Write a {@code fixed64} field, including tag, to the stream. */
1558cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public void writeFixed64(final int fieldNumber, final long value)
1568cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                           throws IOException {
1578cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeTag(fieldNumber, WireFormatMicro.WIRETYPE_FIXED64);
1588cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeFixed64NoTag(value);
1598cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
1608cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
1618cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /** Write a {@code fixed32} field, including tag, to the stream. */
1628cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public void writeFixed32(final int fieldNumber, final int value)
1638cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                           throws IOException {
1648cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeTag(fieldNumber, WireFormatMicro.WIRETYPE_FIXED32);
1658cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeFixed32NoTag(value);
1668cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
1678cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
1688cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /** Write a {@code bool} field, including tag, to the stream. */
1698cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public void writeBool(final int fieldNumber, final boolean value)
1708cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                        throws IOException {
1718cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeTag(fieldNumber, WireFormatMicro.WIRETYPE_VARINT);
1728cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeBoolNoTag(value);
1738cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
1748cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
1758cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /** Write a {@code string} field, including tag, to the stream. */
1768cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public void writeString(final int fieldNumber, final String value)
1778cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                          throws IOException {
1788cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeTag(fieldNumber, WireFormatMicro.WIRETYPE_LENGTH_DELIMITED);
1798cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeStringNoTag(value);
1808cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
1818cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
1828cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /** Write a {@code StringUtf8Micro} field, including tag, to the stream. */
1838cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public void writeStringUtf8(final int fieldNumber, final StringUtf8Micro value)
1848cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                          throws IOException {
1858cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeTag(fieldNumber, WireFormatMicro.WIRETYPE_LENGTH_DELIMITED);
1868cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeStringUtf8NoTag(value);
1878cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
1888cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
1898cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /** Write a {@code group} field, including tag, to the stream. */
1908cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public void writeGroup(final int fieldNumber, final MessageMicro value)
1918cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                         throws IOException {
1928cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeTag(fieldNumber, WireFormatMicro.WIRETYPE_START_GROUP);
1938cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeGroupNoTag(value);
1948cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeTag(fieldNumber, WireFormatMicro.WIRETYPE_END_GROUP);
1958cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
1968cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
1978cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /** Write an embedded message field, including tag, to the stream. */
1988cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public void writeMessage(final int fieldNumber, final MessageMicro value)
1998cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                           throws IOException {
2008cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeTag(fieldNumber, WireFormatMicro.WIRETYPE_LENGTH_DELIMITED);
2018cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeMessageNoTag(value);
2028cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
2038cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
2048cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /** Write a {@code bytes} field, including tag, to the stream. */
2058cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public void writeBytes(final int fieldNumber, final ByteStringMicro value)
2068cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                         throws IOException {
2078cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeTag(fieldNumber, WireFormatMicro.WIRETYPE_LENGTH_DELIMITED);
2088cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeBytesNoTag(value);
2098cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
2108cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
2118cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /** Write a {@code uint32} field, including tag, to the stream. */
2128cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public void writeUInt32(final int fieldNumber, final int value)
2138cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                          throws IOException {
2148cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeTag(fieldNumber, WireFormatMicro.WIRETYPE_VARINT);
2158cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeUInt32NoTag(value);
2168cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
2178cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
2188cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /**
2198cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * Write an enum field, including tag, to the stream.  Caller is responsible
2208cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * for converting the enum value to its numeric value.
2218cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   */
2228cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public void writeEnum(final int fieldNumber, final int value)
2238cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                        throws IOException {
2248cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeTag(fieldNumber, WireFormatMicro.WIRETYPE_VARINT);
2258cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeEnumNoTag(value);
2268cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
2278cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
2288cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /** Write an {@code sfixed32} field, including tag, to the stream. */
2298cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public void writeSFixed32(final int fieldNumber, final int value)
2308cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                            throws IOException {
2318cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeTag(fieldNumber, WireFormatMicro.WIRETYPE_FIXED32);
2328cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeSFixed32NoTag(value);
2338cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
2348cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
2358cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /** Write an {@code sfixed64} field, including tag, to the stream. */
2368cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public void writeSFixed64(final int fieldNumber, final long value)
2378cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                            throws IOException {
2388cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeTag(fieldNumber, WireFormatMicro.WIRETYPE_FIXED64);
2398cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeSFixed64NoTag(value);
2408cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
2418cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
2428cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /** Write an {@code sint32} field, including tag, to the stream. */
2438cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public void writeSInt32(final int fieldNumber, final int value)
2448cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                          throws IOException {
2458cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeTag(fieldNumber, WireFormatMicro.WIRETYPE_VARINT);
2468cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeSInt32NoTag(value);
2478cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
2488cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
2498cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /** Write an {@code sint64} field, including tag, to the stream. */
2508cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public void writeSInt64(final int fieldNumber, final long value)
2518cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                          throws IOException {
2528cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeTag(fieldNumber, WireFormatMicro.WIRETYPE_VARINT);
2538cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeSInt64NoTag(value);
2548cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
2558cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
2568cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /**
2578cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * Write a MessageSet extension field to the stream.  For historical reasons,
2588cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * the wire format differs from normal fields.
2598cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   */
2608cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com//  public void writeMessageSetExtension(final int fieldNumber,
2618cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com//                                       final MessageMicro value)
2628cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com//                                       throws IOException {
2638cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com//    writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_START_GROUP);
2648cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com//    writeUInt32(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber);
2658cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com//    writeMessage(WireFormatMicro.MESSAGE_SET_MESSAGE, value);
2668cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com//    writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_END_GROUP);
2678cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com//  }
2688cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
2698cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /**
2708cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * Write an unparsed MessageSet extension field to the stream.  For
2718cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * historical reasons, the wire format differs from normal fields.
2728cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   */
2738cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com//  public void writeRawMessageSetExtension(final int fieldNumber,
2748cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com//                                          final ByteStringMicro value)
2758cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com//                                          throws IOException {
2768cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com//    writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_START_GROUP);
2778cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com//    writeUInt32(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber);
2788cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com//    writeBytes(WireFormatMicro.MESSAGE_SET_MESSAGE, value);
2798cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com//    writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_END_GROUP);
2808cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com//  }
2818cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
2828cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  // -----------------------------------------------------------------
2838cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
2848cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /** Write a {@code double} field to the stream. */
2858cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public void writeDoubleNoTag(final double value) throws IOException {
2868cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeRawLittleEndian64(Double.doubleToLongBits(value));
2878cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
2888cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
2898cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /** Write a {@code float} field to the stream. */
2908cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public void writeFloatNoTag(final float value) throws IOException {
2918cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeRawLittleEndian32(Float.floatToIntBits(value));
2928cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
2938cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
2948cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /** Write a {@code uint64} field to the stream. */
2958cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public void writeUInt64NoTag(final long value) throws IOException {
2968cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeRawVarint64(value);
2978cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
2988cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
2998cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /** Write an {@code int64} field to the stream. */
3008cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public void writeInt64NoTag(final long value) throws IOException {
3018cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeRawVarint64(value);
3028cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
3038cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
3048cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /** Write an {@code int32} field to the stream. */
3058cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public void writeInt32NoTag(final int value) throws IOException {
3068cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    if (value >= 0) {
3078cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com      writeRawVarint32(value);
3088cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    } else {
3098cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com      // Must sign-extend.
3108cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com      writeRawVarint64(value);
3118cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    }
3128cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
3138cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
3148cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /** Write a {@code fixed64} field to the stream. */
3158cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public void writeFixed64NoTag(final long value) throws IOException {
3168cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeRawLittleEndian64(value);
3178cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
3188cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
3198cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /** Write a {@code fixed32} field to the stream. */
3208cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public void writeFixed32NoTag(final int value) throws IOException {
3218cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeRawLittleEndian32(value);
3228cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
3238cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
3248cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /** Write a {@code bool} field to the stream. */
3258cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public void writeBoolNoTag(final boolean value) throws IOException {
3268cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeRawByte(value ? 1 : 0);
3278cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
3288cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
3298cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /** Write a {@code string} field to the stream. */
3308cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public void writeStringNoTag(final String value) throws IOException {
3318cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    // Unfortunately there does not appear to be any way to tell Java to encode
3328cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    // UTF-8 directly into our buffer, so we have to let it create its own byte
3338cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    // array and then copy.
3348cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    final byte[] bytes = value.getBytes("UTF-8");
3358cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeRawVarint32(bytes.length);
3368cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeRawBytes(bytes);
3378cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
3388cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
3398cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /** Write a {@code StringUtf8Micro} field to the stream. */
3408cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public void writeStringUtf8NoTag(final StringUtf8Micro value) throws IOException {
3418cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    final byte[] bytes = value.getBytes();
3428cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeRawVarint32(bytes.length);
3438cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeRawBytes(bytes);
3448cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
3458cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
3468cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /** Write a {@code group} field to the stream. */
3478cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public void writeGroupNoTag(final MessageMicro value) throws IOException {
3488cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    value.writeTo(this);
3498cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
3508cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
3518cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /** Write an embedded message field to the stream. */
3528cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public void writeMessageNoTag(final MessageMicro value) throws IOException {
3538cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeRawVarint32(value.getCachedSize());
3548cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    value.writeTo(this);
3558cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
3568cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
3578cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /** Write a {@code bytes} field to the stream. */
3588cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public void writeBytesNoTag(final ByteStringMicro value) throws IOException {
3598cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    final byte[] bytes = value.toByteArray();
3608cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeRawVarint32(bytes.length);
3618cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeRawBytes(bytes);
3628cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
3638cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
3648cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /** Write a {@code uint32} field to the stream. */
3658cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public void writeUInt32NoTag(final int value) throws IOException {
3668cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeRawVarint32(value);
3678cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
3688cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
3698cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /**
3708cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * Write an enum field to the stream.  Caller is responsible
3718cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * for converting the enum value to its numeric value.
3728cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   */
3738cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public void writeEnumNoTag(final int value) throws IOException {
3748cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeRawVarint32(value);
3758cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
3768cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
3778cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /** Write an {@code sfixed32} field to the stream. */
3788cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public void writeSFixed32NoTag(final int value) throws IOException {
3798cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeRawLittleEndian32(value);
3808cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
3818cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
3828cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /** Write an {@code sfixed64} field to the stream. */
3838cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public void writeSFixed64NoTag(final long value) throws IOException {
3848cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeRawLittleEndian64(value);
3858cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
3868cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
3878cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /** Write an {@code sint32} field to the stream. */
3888cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public void writeSInt32NoTag(final int value) throws IOException {
3898cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeRawVarint32(encodeZigZag32(value));
3908cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
3918cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
3928cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /** Write an {@code sint64} field to the stream. */
3938cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public void writeSInt64NoTag(final long value) throws IOException {
3948cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    writeRawVarint64(encodeZigZag64(value));
3958cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
3968cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
3978cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  // =================================================================
3988cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
3998cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /**
4008cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * Compute the number of bytes that would be needed to encode a
4018cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * {@code double} field, including tag.
4028cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   */
4038cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public static int computeDoubleSize(final int fieldNumber,
4048cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                                      final double value) {
4058cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    return computeTagSize(fieldNumber) + computeDoubleSizeNoTag(value);
4068cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
4078cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
4088cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /**
4098cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * Compute the number of bytes that would be needed to encode a
4108cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * {@code float} field, including tag.
4118cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   */
4128cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public static int computeFloatSize(final int fieldNumber, final float value) {
4138cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    return computeTagSize(fieldNumber) + computeFloatSizeNoTag(value);
4148cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
4158cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
4168cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /**
4178cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * Compute the number of bytes that would be needed to encode a
4188cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * {@code uint64} field, including tag.
4198cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   */
4208cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public static int computeUInt64Size(final int fieldNumber, final long value) {
4218cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    return computeTagSize(fieldNumber) + computeUInt64SizeNoTag(value);
4228cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
4238cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
4248cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /**
4258cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * Compute the number of bytes that would be needed to encode an
4268cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * {@code int64} field, including tag.
4278cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   */
4288cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public static int computeInt64Size(final int fieldNumber, final long value) {
4298cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    return computeTagSize(fieldNumber) + computeInt64SizeNoTag(value);
4308cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
4318cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
4328cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /**
4338cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * Compute the number of bytes that would be needed to encode an
4348cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * {@code int32} field, including tag.
4358cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   */
4368cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public static int computeInt32Size(final int fieldNumber, final int value) {
4378cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    return computeTagSize(fieldNumber) + computeInt32SizeNoTag(value);
4388cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
4398cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
4408cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /**
4418cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * Compute the number of bytes that would be needed to encode a
4428cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * {@code fixed64} field, including tag.
4438cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   */
4448cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public static int computeFixed64Size(final int fieldNumber,
4458cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                                       final long value) {
4468cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    return computeTagSize(fieldNumber) + computeFixed64SizeNoTag(value);
4478cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
4488cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
4498cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /**
4508cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * Compute the number of bytes that would be needed to encode a
4518cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * {@code fixed32} field, including tag.
4528cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   */
4538cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public static int computeFixed32Size(final int fieldNumber,
4548cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                                       final int value) {
4558cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    return computeTagSize(fieldNumber) + computeFixed32SizeNoTag(value);
4568cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
4578cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
4588cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /**
4598cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * Compute the number of bytes that would be needed to encode a
4608cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * {@code bool} field, including tag.
4618cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   */
4628cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public static int computeBoolSize(final int fieldNumber,
4638cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                                    final boolean value) {
4648cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    return computeTagSize(fieldNumber) + computeBoolSizeNoTag(value);
4658cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
4668cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
4678cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /**
4688cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * Compute the number of bytes that would be needed to encode a
4698cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * {@code string} field, including tag.
4708cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   */
4718cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public static int computeStringSize(final int fieldNumber,
4728cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                                      final String value) {
4738cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    return computeTagSize(fieldNumber) + computeStringSizeNoTag(value);
4748cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
4758cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
4768cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /**
4778cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * Compute the number of bytes that would be needed to encode a
4788cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * {@code StringUtf8Micro} field, including tag.
4798cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   */
4808cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public static int computeStringUtf8Size(final int fieldNumber,
4818cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                                      final StringUtf8Micro value) {
4828cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    return computeTagSize(fieldNumber) + computeStringUtf8SizeNoTag(value);
4838cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
4848cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
4858cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /**
4868cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * Compute the number of bytes that would be needed to encode a
4878cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * {@code group} field, including tag.
4888cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   */
4898cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public static int computeGroupSize(final int fieldNumber,
4908cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                                     final MessageMicro value) {
4918cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    return computeTagSize(fieldNumber) * 2 + computeGroupSizeNoTag(value);
4928cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
4938cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
4948cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /**
4958cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * Compute the number of bytes that would be needed to encode an
4968cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * embedded message field, including tag.
4978cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   */
4988cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public static int computeMessageSize(final int fieldNumber,
4998cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                                       final MessageMicro value) {
5008cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    return computeTagSize(fieldNumber) + computeMessageSizeNoTag(value);
5018cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
5028cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
5038cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /**
5048cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * Compute the number of bytes that would be needed to encode a
5058cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * {@code bytes} field, including tag.
5068cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   */
5078cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public static int computeBytesSize(final int fieldNumber,
5088cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com                                     final ByteStringMicro value) {
5098cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    return computeTagSize(fieldNumber) + computeBytesSizeNoTag(value);
5108cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
5118cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
5128cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /**
5138cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * Compute the number of bytes that would be needed to encode a
5148cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * {@code uint32} field, including tag.
5158cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   */
5168cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public static int computeUInt32Size(final int fieldNumber, final int value) {
5178cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    return computeTagSize(fieldNumber) + computeUInt32SizeNoTag(value);
5188cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
5198cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
5208cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  /**
5218cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * Compute the number of bytes that would be needed to encode an
5228cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * enum field, including tag.  Caller is responsible for converting the
5238cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   * enum value to its numeric value.
5248cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com   */
5258cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  public static int computeEnumSize(final int fieldNumber, final int value) {
5268cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com    return computeTagSize(fieldNumber) + computeEnumSizeNoTag(value);
5278cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com  }
5288cee797901763ab0922eb9ef484cfdcbc94bee54edisonn@google.com
529cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com  /**
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 StringUtf8Micro} field.
675   */
676  public static int computeStringUtf8SizeNoTag(final StringUtf8Micro value) {
677    final byte[] bytes = value.getBytes();
678    return computeRawVarint32Size(bytes.length) +
679             bytes.length;
680  }
681
682  /**
683   * Compute the number of bytes that would be needed to encode a
684   * {@code group} field.
685   */
686  public static int computeGroupSizeNoTag(final MessageMicro value) {
687    return value.getCachedSize();
688  }
689
690  /**
691   * Compute the number of bytes that would be needed to encode an embedded
692   * message field.
693   */
694  public static int computeMessageSizeNoTag(final MessageMicro value) {
695    final int size = value.getCachedSize();
696    return computeRawVarint32Size(size) + size;
697  }
698
699  /**
700   * Compute the number of bytes that would be needed to encode a
701   * {@code bytes} field.
702   */
703  public static int computeBytesSizeNoTag(final ByteStringMicro value) {
704    return computeRawVarint32Size(value.size()) +
705           value.size();
706  }
707
708  /**
709   * Compute the number of bytes that would be needed to encode a
710   * {@code uint32} field.
711   */
712  public static int computeUInt32SizeNoTag(final int value) {
713    return computeRawVarint32Size(value);
714  }
715
716  /**
717   * Compute the number of bytes that would be needed to encode an enum field.
718   * Caller is responsible for converting the enum value to its numeric value.
719   */
720  public static int computeEnumSizeNoTag(final int value) {
721    return computeRawVarint32Size(value);
722  }
723
724  /**
725   * Compute the number of bytes that would be needed to encode an
726   * {@code sfixed32} field.
727   */
728  public static int computeSFixed32SizeNoTag(final int value) {
729    return LITTLE_ENDIAN_32_SIZE;
730  }
731
732  /**
733   * Compute the number of bytes that would be needed to encode an
734   * {@code sfixed64} field.
735   */
736  public static int computeSFixed64SizeNoTag(final long value) {
737    return LITTLE_ENDIAN_64_SIZE;
738  }
739
740  /**
741   * Compute the number of bytes that would be needed to encode an
742   * {@code sint32} field.
743   */
744  public static int computeSInt32SizeNoTag(final int value) {
745    return computeRawVarint32Size(encodeZigZag32(value));
746  }
747
748  /**
749   * Compute the number of bytes that would be needed to encode an
750   * {@code sint64} field.
751   */
752  public static int computeSInt64SizeNoTag(final long value) {
753    return computeRawVarint64Size(encodeZigZag64(value));
754  }
755
756  // =================================================================
757
758  /**
759   * Internal helper that writes the current buffer to the output. The
760   * buffer position is reset to its initial value when this returns.
761   */
762  private void refreshBuffer() throws IOException {
763    if (output == null) {
764      // We're writing to a single buffer.
765      throw new OutOfSpaceException();
766    }
767
768    // Since we have an output stream, this is our buffer
769    // and buffer offset == 0
770    output.write(buffer, 0, position);
771    position = 0;
772  }
773
774  /**
775   * Flushes the stream and forces any buffered bytes to be written.  This
776   * does not flush the underlying OutputStream.
777   */
778  public void flush() throws IOException {
779    if (output != null) {
780      refreshBuffer();
781    }
782  }
783
784  /**
785   * If writing to a flat array, return the space left in the array.
786   * Otherwise, throws {@code UnsupportedOperationException}.
787   */
788  public int spaceLeft() {
789    if (output == null) {
790      return limit - position;
791    } else {
792      throw new UnsupportedOperationException(
793        "spaceLeft() can only be called on CodedOutputStreams that are " +
794        "writing to a flat array.");
795    }
796  }
797
798  /**
799   * Verifies that {@link #spaceLeft()} returns zero.  It's common to create
800   * a byte array that is exactly big enough to hold a message, then write to
801   * it with a {@code CodedOutputStream}.  Calling {@code checkNoSpaceLeft()}
802   * after writing verifies that the message was actually as big as expected,
803   * which can help catch bugs.
804   */
805  public void checkNoSpaceLeft() {
806    if (spaceLeft() != 0) {
807      throw new IllegalStateException(
808        "Did not write as much data as expected.");
809    }
810  }
811
812  /**
813   * If you create a CodedOutputStream around a simple flat array, you must
814   * not attempt to write more bytes than the array has space.  Otherwise,
815   * this exception will be thrown.
816   */
817  public static class OutOfSpaceException extends IOException {
818    private static final long serialVersionUID = -6947486886997889499L;
819
820    OutOfSpaceException() {
821      super("CodedOutputStream was writing to a flat byte array and ran " +
822            "out of space.");
823    }
824  }
825
826  /** Write a single byte. */
827  public void writeRawByte(final byte value) throws IOException {
828    if (position == limit) {
829      refreshBuffer();
830    }
831
832    buffer[position++] = value;
833  }
834
835  /** Write a single byte, represented by an integer value. */
836  public void writeRawByte(final int value) throws IOException {
837    writeRawByte((byte) value);
838  }
839
840  /** Write an array of bytes. */
841  public void writeRawBytes(final byte[] value) throws IOException {
842    writeRawBytes(value, 0, value.length);
843  }
844
845  /** Write part of an array of bytes. */
846  public void writeRawBytes(final byte[] value, int offset, int length)
847                            throws IOException {
848    if (limit - position >= length) {
849      // We have room in the current buffer.
850      System.arraycopy(value, offset, buffer, position, length);
851      position += length;
852    } else {
853      // Write extends past current buffer.  Fill the rest of this buffer and
854      // flush.
855      final int bytesWritten = limit - position;
856      System.arraycopy(value, offset, buffer, position, bytesWritten);
857      offset += bytesWritten;
858      length -= bytesWritten;
859      position = limit;
860      refreshBuffer();
861
862      // Now deal with the rest.
863      // Since we have an output stream, this is our buffer
864      // and buffer offset == 0
865      if (length <= limit) {
866        // Fits in new buffer.
867        System.arraycopy(value, offset, buffer, 0, length);
868        position = length;
869      } else {
870        // Write is very big.  Let's do it all at once.
871        output.write(value, offset, length);
872      }
873    }
874  }
875
876  /** Encode and write a tag. */
877  public void writeTag(final int fieldNumber, final int wireType)
878                       throws IOException {
879    writeRawVarint32(WireFormatMicro.makeTag(fieldNumber, wireType));
880  }
881
882  /** Compute the number of bytes that would be needed to encode a tag. */
883  public static int computeTagSize(final int fieldNumber) {
884    return computeRawVarint32Size(WireFormatMicro.makeTag(fieldNumber, 0));
885  }
886
887  /**
888   * Encode and write a varint.  {@code value} is treated as
889   * unsigned, so it won't be sign-extended if negative.
890   */
891  public void writeRawVarint32(int value) throws IOException {
892    while (true) {
893      if ((value & ~0x7F) == 0) {
894        writeRawByte(value);
895        return;
896      } else {
897        writeRawByte((value & 0x7F) | 0x80);
898        value >>>= 7;
899      }
900    }
901  }
902
903  /**
904   * Compute the number of bytes that would be needed to encode a varint.
905   * {@code value} is treated as unsigned, so it won't be sign-extended if
906   * negative.
907   */
908  public static int computeRawVarint32Size(final int value) {
909    if ((value & (0xffffffff <<  7)) == 0) return 1;
910    if ((value & (0xffffffff << 14)) == 0) return 2;
911    if ((value & (0xffffffff << 21)) == 0) return 3;
912    if ((value & (0xffffffff << 28)) == 0) return 4;
913    return 5;
914  }
915
916  /** Encode and write a varint. */
917  public void writeRawVarint64(long value) throws IOException {
918    while (true) {
919      if ((value & ~0x7FL) == 0) {
920        writeRawByte((int)value);
921        return;
922      } else {
923        writeRawByte(((int)value & 0x7F) | 0x80);
924        value >>>= 7;
925      }
926    }
927  }
928
929  /** Compute the number of bytes that would be needed to encode a varint. */
930  public static int computeRawVarint64Size(final long value) {
931    if ((value & (0xffffffffffffffffL <<  7)) == 0) return 1;
932    if ((value & (0xffffffffffffffffL << 14)) == 0) return 2;
933    if ((value & (0xffffffffffffffffL << 21)) == 0) return 3;
934    if ((value & (0xffffffffffffffffL << 28)) == 0) return 4;
935    if ((value & (0xffffffffffffffffL << 35)) == 0) return 5;
936    if ((value & (0xffffffffffffffffL << 42)) == 0) return 6;
937    if ((value & (0xffffffffffffffffL << 49)) == 0) return 7;
938    if ((value & (0xffffffffffffffffL << 56)) == 0) return 8;
939    if ((value & (0xffffffffffffffffL << 63)) == 0) return 9;
940    return 10;
941  }
942
943  /** Write a little-endian 32-bit integer. */
944  public void writeRawLittleEndian32(final int value) throws IOException {
945    writeRawByte((value      ) & 0xFF);
946    writeRawByte((value >>  8) & 0xFF);
947    writeRawByte((value >> 16) & 0xFF);
948    writeRawByte((value >> 24) & 0xFF);
949  }
950
951  public static final int LITTLE_ENDIAN_32_SIZE = 4;
952
953  /** Write a little-endian 64-bit integer. */
954  public void writeRawLittleEndian64(final long value) throws IOException {
955    writeRawByte((int)(value      ) & 0xFF);
956    writeRawByte((int)(value >>  8) & 0xFF);
957    writeRawByte((int)(value >> 16) & 0xFF);
958    writeRawByte((int)(value >> 24) & 0xFF);
959    writeRawByte((int)(value >> 32) & 0xFF);
960    writeRawByte((int)(value >> 40) & 0xFF);
961    writeRawByte((int)(value >> 48) & 0xFF);
962    writeRawByte((int)(value >> 56) & 0xFF);
963  }
964
965  public static final int LITTLE_ENDIAN_64_SIZE = 8;
966
967  /**
968   * Encode a ZigZag-encoded 32-bit value.  ZigZag encodes signed integers
969   * into values that can be efficiently encoded with varint.  (Otherwise,
970   * negative values must be sign-extended to 64 bits to be varint encoded,
971   * thus always taking 10 bytes on the wire.)
972   *
973   * @param n A signed 32-bit integer.
974   * @return An unsigned 32-bit integer, stored in a signed int because
975   *         Java has no explicit unsigned support.
976   */
977  public static int encodeZigZag32(final int n) {
978    // Note:  the right-shift must be arithmetic
979    return (n << 1) ^ (n >> 31);
980  }
981
982  /**
983   * Encode a ZigZag-encoded 64-bit value.  ZigZag encodes signed integers
984   * into values that can be efficiently encoded with varint.  (Otherwise,
985   * negative values must be sign-extended to 64 bits to be varint encoded,
986   * thus always taking 10 bytes on the wire.)
987   *
988   * @param n A signed 64-bit integer.
989   * @return An unsigned 64-bit integer, stored in a signed int because
990   *         Java has no explicit unsigned support.
991   */
992  public static long encodeZigZag64(final long n) {
993    // Note:  the right-shift must be arithmetic
994    return (n << 1) ^ (n >> 63);
995  }
996}
997