Blame | Last modification | View Log | Download | RSS feed
// Protocol Buffers - Google's data interchange format// Copyright 2008 Google Inc. All rights reserved.// http://code.google.com/p/protobuf///// Redistribution and use in source and binary forms, with or without// modification, are permitted provided that the following conditions are// met://// * Redistributions of source code must retain the above copyright// notice, this list of conditions and the following disclaimer.// * Redistributions in binary form must reproduce the above// copyright notice, this list of conditions and the following disclaimer// in the documentation and/or other materials provided with the// distribution.// * Neither the name of Google Inc. nor the names of its// contributors may be used to endorse or promote products derived from// this software without specific prior written permission.//// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.package com.google.protobuf;import java.io.OutputStream;import java.io.IOException;import java.io.UnsupportedEncodingException;import java.io.InputStream;/*** Encodes and writes protocol message fields.** <p>This class contains two kinds of methods: methods that write specific* protocol message constructs and field types (e.g. {@link #writeTag} and* {@link #writeInt32}) and methods that write low-level values (e.g.* {@link #writeRawVarint32} and {@link #writeRawBytes}). If you are* writing encoded protocol messages, you should use the former methods, but if* you are writing some other format of your own design, use the latter.** <p>This class is totally unsynchronized.** @author kneton@google.com Kenton Varda*/public final class CodedOutputStream {private final byte[] buffer;private final int limit;private int position;private final OutputStream output;/*** The buffer size used in {@link #newInstance(OutputStream)}.*/public static final int DEFAULT_BUFFER_SIZE = 4096;/*** Returns the buffer size to efficiently write dataLength bytes to this* CodedOutputStream. Used by AbstractMessageLite.** @return the buffer size to efficiently write dataLength bytes to this* CodedOutputStream.*/static int computePreferredBufferSize(int dataLength) {if (dataLength > DEFAULT_BUFFER_SIZE) return DEFAULT_BUFFER_SIZE;return dataLength;}private CodedOutputStream(final byte[] buffer, final int offset,final int length) {output = null;this.buffer = buffer;position = offset;limit = offset + length;}private CodedOutputStream(final OutputStream output, final byte[] buffer) {this.output = output;this.buffer = buffer;position = 0;limit = buffer.length;}/*** Create a new {@code CodedOutputStream} wrapping the given* {@code OutputStream}.*/public static CodedOutputStream newInstance(final OutputStream output) {return newInstance(output, DEFAULT_BUFFER_SIZE);}/*** Create a new {@code CodedOutputStream} wrapping the given* {@code OutputStream} with a given buffer size.*/public static CodedOutputStream newInstance(final OutputStream output,final int bufferSize) {return new CodedOutputStream(output, new byte[bufferSize]);}/*** Create a new {@code CodedOutputStream} that writes directly to the given* byte array. If more bytes are written than fit in the array,* {@link OutOfSpaceException} will be thrown. Writing directly to a flat* array is faster than writing to an {@code OutputStream}. See also* {@link ByteString#newCodedBuilder}.*/public static CodedOutputStream newInstance(final byte[] flatArray) {return newInstance(flatArray, 0, flatArray.length);}/*** Create a new {@code CodedOutputStream} that writes directly to the given* byte array slice. If more bytes are written than fit in the slice,* {@link OutOfSpaceException} will be thrown. Writing directly to a flat* array is faster than writing to an {@code OutputStream}. See also* {@link ByteString#newCodedBuilder}.*/public static CodedOutputStream newInstance(final byte[] flatArray,final int offset,final int length) {return new CodedOutputStream(flatArray, offset, length);}// -----------------------------------------------------------------/** Write a {@code double} field, including tag, to the stream. */public void writeDouble(final int fieldNumber, final double value)throws IOException {writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);writeDoubleNoTag(value);}/** Write a {@code float} field, including tag, to the stream. */public void writeFloat(final int fieldNumber, final float value)throws IOException {writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);writeFloatNoTag(value);}/** Write a {@code uint64} field, including tag, to the stream. */public void writeUInt64(final int fieldNumber, final long value)throws IOException {writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);writeUInt64NoTag(value);}/** Write an {@code int64} field, including tag, to the stream. */public void writeInt64(final int fieldNumber, final long value)throws IOException {writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);writeInt64NoTag(value);}/** Write an {@code int32} field, including tag, to the stream. */public void writeInt32(final int fieldNumber, final int value)throws IOException {writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);writeInt32NoTag(value);}/** Write a {@code fixed64} field, including tag, to the stream. */public void writeFixed64(final int fieldNumber, final long value)throws IOException {writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);writeFixed64NoTag(value);}/** Write a {@code fixed32} field, including tag, to the stream. */public void writeFixed32(final int fieldNumber, final int value)throws IOException {writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);writeFixed32NoTag(value);}/** Write a {@code bool} field, including tag, to the stream. */public void writeBool(final int fieldNumber, final boolean value)throws IOException {writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);writeBoolNoTag(value);}/** Write a {@code string} field, including tag, to the stream. */public void writeString(final int fieldNumber, final String value)throws IOException {writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);writeStringNoTag(value);}/** Write a {@code group} field, including tag, to the stream. */public void writeGroup(final int fieldNumber, final MessageLite value)throws IOException {writeTag(fieldNumber, WireFormat.WIRETYPE_START_GROUP);writeGroupNoTag(value);writeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP);}/*** Write a group represented by an {@link UnknownFieldSet}.** @deprecated UnknownFieldSet now implements MessageLite, so you can just* call {@link #writeGroup}.*/@Deprecatedpublic void writeUnknownGroup(final int fieldNumber,final MessageLite value)throws IOException {writeGroup(fieldNumber, value);}/** Write an embedded message field, including tag, to the stream. */public void writeMessage(final int fieldNumber, final MessageLite value)throws IOException {writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);writeMessageNoTag(value);}/** Write a {@code bytes} field, including tag, to the stream. */public void writeBytes(final int fieldNumber, final ByteString value)throws IOException {writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);writeBytesNoTag(value);}/** Write a {@code uint32} field, including tag, to the stream. */public void writeUInt32(final int fieldNumber, final int value)throws IOException {writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);writeUInt32NoTag(value);}/*** Write an enum field, including tag, to the stream. Caller is responsible* for converting the enum value to its numeric value.*/public void writeEnum(final int fieldNumber, final int value)throws IOException {writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);writeEnumNoTag(value);}/** Write an {@code sfixed32} field, including tag, to the stream. */public void writeSFixed32(final int fieldNumber, final int value)throws IOException {writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);writeSFixed32NoTag(value);}/** Write an {@code sfixed64} field, including tag, to the stream. */public void writeSFixed64(final int fieldNumber, final long value)throws IOException {writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);writeSFixed64NoTag(value);}/** Write an {@code sint32} field, including tag, to the stream. */public void writeSInt32(final int fieldNumber, final int value)throws IOException {writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);writeSInt32NoTag(value);}/** Write an {@code sint64} field, including tag, to the stream. */public void writeSInt64(final int fieldNumber, final long value)throws IOException {writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);writeSInt64NoTag(value);}/*** Write a MessageSet extension field to the stream. For historical reasons,* the wire format differs from normal fields.*/public void writeMessageSetExtension(final int fieldNumber,final MessageLite value)throws IOException {writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);writeMessage(WireFormat.MESSAGE_SET_MESSAGE, value);writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);}/*** Write an unparsed MessageSet extension field to the stream. For* historical reasons, the wire format differs from normal fields.*/public void writeRawMessageSetExtension(final int fieldNumber,final ByteString value)throws IOException {writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);writeBytes(WireFormat.MESSAGE_SET_MESSAGE, value);writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);}// -----------------------------------------------------------------/** Write a {@code double} field to the stream. */public void writeDoubleNoTag(final double value) throws IOException {writeRawLittleEndian64(Double.doubleToRawLongBits(value));}/** Write a {@code float} field to the stream. */public void writeFloatNoTag(final float value) throws IOException {writeRawLittleEndian32(Float.floatToRawIntBits(value));}/** Write a {@code uint64} field to the stream. */public void writeUInt64NoTag(final long value) throws IOException {writeRawVarint64(value);}/** Write an {@code int64} field to the stream. */public void writeInt64NoTag(final long value) throws IOException {writeRawVarint64(value);}/** Write an {@code int32} field to the stream. */public void writeInt32NoTag(final int value) throws IOException {if (value >= 0) {writeRawVarint32(value);} else {// Must sign-extend.writeRawVarint64(value);}}/** Write a {@code fixed64} field to the stream. */public void writeFixed64NoTag(final long value) throws IOException {writeRawLittleEndian64(value);}/** Write a {@code fixed32} field to the stream. */public void writeFixed32NoTag(final int value) throws IOException {writeRawLittleEndian32(value);}/** Write a {@code bool} field to the stream. */public void writeBoolNoTag(final boolean value) throws IOException {writeRawByte(value ? 1 : 0);}/** Write a {@code string} field to the stream. */public void writeStringNoTag(final String value) throws IOException {// Unfortunately there does not appear to be any way to tell Java to encode// UTF-8 directly into our buffer, so we have to let it create its own byte// array and then copy.final byte[] bytes = value.getBytes("UTF-8");writeRawVarint32(bytes.length);writeRawBytes(bytes);}/** Write a {@code group} field to the stream. */public void writeGroupNoTag(final MessageLite value) throws IOException {value.writeTo(this);}/*** Write a group represented by an {@link UnknownFieldSet}.** @deprecated UnknownFieldSet now implements MessageLite, so you can just* call {@link #writeGroupNoTag}.*/@Deprecatedpublic void writeUnknownGroupNoTag(final MessageLite value)throws IOException {writeGroupNoTag(value);}/** Write an embedded message field to the stream. */public void writeMessageNoTag(final MessageLite value) throws IOException {writeRawVarint32(value.getSerializedSize());value.writeTo(this);}/** Write a {@code bytes} field to the stream. */public void writeBytesNoTag(final ByteString value) throws IOException {writeRawVarint32(value.size());writeRawBytes(value);}/** Write a {@code uint32} field to the stream. */public void writeUInt32NoTag(final int value) throws IOException {writeRawVarint32(value);}/*** Write an enum field to the stream. Caller is responsible* for converting the enum value to its numeric value.*/public void writeEnumNoTag(final int value) throws IOException {writeInt32NoTag(value);}/** Write an {@code sfixed32} field to the stream. */public void writeSFixed32NoTag(final int value) throws IOException {writeRawLittleEndian32(value);}/** Write an {@code sfixed64} field to the stream. */public void writeSFixed64NoTag(final long value) throws IOException {writeRawLittleEndian64(value);}/** Write an {@code sint32} field to the stream. */public void writeSInt32NoTag(final int value) throws IOException {writeRawVarint32(encodeZigZag32(value));}/** Write an {@code sint64} field to the stream. */public void writeSInt64NoTag(final long value) throws IOException {writeRawVarint64(encodeZigZag64(value));}// =================================================================/*** Compute the number of bytes that would be needed to encode a* {@code double} field, including tag.*/public static int computeDoubleSize(final int fieldNumber,final double value) {return computeTagSize(fieldNumber) + computeDoubleSizeNoTag(value);}/*** Compute the number of bytes that would be needed to encode a* {@code float} field, including tag.*/public static int computeFloatSize(final int fieldNumber, final float value) {return computeTagSize(fieldNumber) + computeFloatSizeNoTag(value);}/*** Compute the number of bytes that would be needed to encode a* {@code uint64} field, including tag.*/public static int computeUInt64Size(final int fieldNumber, final long value) {return computeTagSize(fieldNumber) + computeUInt64SizeNoTag(value);}/*** Compute the number of bytes that would be needed to encode an* {@code int64} field, including tag.*/public static int computeInt64Size(final int fieldNumber, final long value) {return computeTagSize(fieldNumber) + computeInt64SizeNoTag(value);}/*** Compute the number of bytes that would be needed to encode an* {@code int32} field, including tag.*/public static int computeInt32Size(final int fieldNumber, final int value) {return computeTagSize(fieldNumber) + computeInt32SizeNoTag(value);}/*** Compute the number of bytes that would be needed to encode a* {@code fixed64} field, including tag.*/public static int computeFixed64Size(final int fieldNumber,final long value) {return computeTagSize(fieldNumber) + computeFixed64SizeNoTag(value);}/*** Compute the number of bytes that would be needed to encode a* {@code fixed32} field, including tag.*/public static int computeFixed32Size(final int fieldNumber,final int value) {return computeTagSize(fieldNumber) + computeFixed32SizeNoTag(value);}/*** Compute the number of bytes that would be needed to encode a* {@code bool} field, including tag.*/public static int computeBoolSize(final int fieldNumber,final boolean value) {return computeTagSize(fieldNumber) + computeBoolSizeNoTag(value);}/*** Compute the number of bytes that would be needed to encode a* {@code string} field, including tag.*/public static int computeStringSize(final int fieldNumber,final String value) {return computeTagSize(fieldNumber) + computeStringSizeNoTag(value);}/*** Compute the number of bytes that would be needed to encode a* {@code group} field, including tag.*/public static int computeGroupSize(final int fieldNumber,final MessageLite value) {return computeTagSize(fieldNumber) * 2 + computeGroupSizeNoTag(value);}/*** Compute the number of bytes that would be needed to encode a* {@code group} field represented by an {@code UnknownFieldSet}, including* tag.** @deprecated UnknownFieldSet now implements MessageLite, so you can just* call {@link #computeGroupSize}.*/@Deprecatedpublic static int computeUnknownGroupSize(final int fieldNumber,final MessageLite value) {return computeGroupSize(fieldNumber, value);}/*** Compute the number of bytes that would be needed to encode an* embedded message field, including tag.*/public static int computeMessageSize(final int fieldNumber,final MessageLite value) {return computeTagSize(fieldNumber) + computeMessageSizeNoTag(value);}/*** Compute the number of bytes that would be needed to encode a* {@code bytes} field, including tag.*/public static int computeBytesSize(final int fieldNumber,final ByteString value) {return computeTagSize(fieldNumber) + computeBytesSizeNoTag(value);}/*** Compute the number of bytes that would be needed to encode a* {@code uint32} field, including tag.*/public static int computeUInt32Size(final int fieldNumber, final int value) {return computeTagSize(fieldNumber) + computeUInt32SizeNoTag(value);}/*** Compute the number of bytes that would be needed to encode an* enum field, including tag. Caller is responsible for converting the* enum value to its numeric value.*/public static int computeEnumSize(final int fieldNumber, final int value) {return computeTagSize(fieldNumber) + computeEnumSizeNoTag(value);}/*** Compute the number of bytes that would be needed to encode an* {@code sfixed32} field, including tag.*/public static int computeSFixed32Size(final int fieldNumber,final int value) {return computeTagSize(fieldNumber) + computeSFixed32SizeNoTag(value);}/*** Compute the number of bytes that would be needed to encode an* {@code sfixed64} field, including tag.*/public static int computeSFixed64Size(final int fieldNumber,final long value) {return computeTagSize(fieldNumber) + computeSFixed64SizeNoTag(value);}/*** Compute the number of bytes that would be needed to encode an* {@code sint32} field, including tag.*/public static int computeSInt32Size(final int fieldNumber, final int value) {return computeTagSize(fieldNumber) + computeSInt32SizeNoTag(value);}/*** Compute the number of bytes that would be needed to encode an* {@code sint64} field, including tag.*/public static int computeSInt64Size(final int fieldNumber, final long value) {return computeTagSize(fieldNumber) + computeSInt64SizeNoTag(value);}/*** Compute the number of bytes that would be needed to encode a* MessageSet extension to the stream. For historical reasons,* the wire format differs from normal fields.*/public static int computeMessageSetExtensionSize(final int fieldNumber, final MessageLite value) {return computeTagSize(WireFormat.MESSAGE_SET_ITEM) * 2 +computeUInt32Size(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber) +computeMessageSize(WireFormat.MESSAGE_SET_MESSAGE, value);}/*** Compute the number of bytes that would be needed to encode an* unparsed MessageSet extension field to the stream. For* historical reasons, the wire format differs from normal fields.*/public static int computeRawMessageSetExtensionSize(final int fieldNumber, final ByteString value) {return computeTagSize(WireFormat.MESSAGE_SET_ITEM) * 2 +computeUInt32Size(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber) +computeBytesSize(WireFormat.MESSAGE_SET_MESSAGE, value);}// -----------------------------------------------------------------/*** Compute the number of bytes that would be needed to encode a* {@code double} field, including tag.*/public static int computeDoubleSizeNoTag(final double value) {return LITTLE_ENDIAN_64_SIZE;}/*** Compute the number of bytes that would be needed to encode a* {@code float} field, including tag.*/public static int computeFloatSizeNoTag(final float value) {return LITTLE_ENDIAN_32_SIZE;}/*** Compute the number of bytes that would be needed to encode a* {@code uint64} field, including tag.*/public static int computeUInt64SizeNoTag(final long value) {return computeRawVarint64Size(value);}/*** Compute the number of bytes that would be needed to encode an* {@code int64} field, including tag.*/public static int computeInt64SizeNoTag(final long value) {return computeRawVarint64Size(value);}/*** Compute the number of bytes that would be needed to encode an* {@code int32} field, including tag.*/public static int computeInt32SizeNoTag(final int value) {if (value >= 0) {return computeRawVarint32Size(value);} else {// Must sign-extend.return 10;}}/*** Compute the number of bytes that would be needed to encode a* {@code fixed64} field.*/public static int computeFixed64SizeNoTag(final long value) {return LITTLE_ENDIAN_64_SIZE;}/*** Compute the number of bytes that would be needed to encode a* {@code fixed32} field.*/public static int computeFixed32SizeNoTag(final int value) {return LITTLE_ENDIAN_32_SIZE;}/*** Compute the number of bytes that would be needed to encode a* {@code bool} field.*/public static int computeBoolSizeNoTag(final boolean value) {return 1;}/*** Compute the number of bytes that would be needed to encode a* {@code string} field.*/public static int computeStringSizeNoTag(final String value) {try {final byte[] bytes = value.getBytes("UTF-8");return computeRawVarint32Size(bytes.length) +bytes.length;} catch (UnsupportedEncodingException e) {throw new RuntimeException("UTF-8 not supported.", e);}}/*** Compute the number of bytes that would be needed to encode a* {@code group} field.*/public static int computeGroupSizeNoTag(final MessageLite value) {return value.getSerializedSize();}/*** Compute the number of bytes that would be needed to encode a* {@code group} field represented by an {@code UnknownFieldSet}, including* tag.** @deprecated UnknownFieldSet now implements MessageLite, so you can just* call {@link #computeUnknownGroupSizeNoTag}.*/@Deprecatedpublic static int computeUnknownGroupSizeNoTag(final MessageLite value) {return computeGroupSizeNoTag(value);}/*** Compute the number of bytes that would be needed to encode an embedded* message field.*/public static int computeMessageSizeNoTag(final MessageLite value) {final int size = value.getSerializedSize();return computeRawVarint32Size(size) + size;}/*** Compute the number of bytes that would be needed to encode a* {@code bytes} field.*/public static int computeBytesSizeNoTag(final ByteString value) {return computeRawVarint32Size(value.size()) +value.size();}/*** Compute the number of bytes that would be needed to encode a* {@code uint32} field.*/public static int computeUInt32SizeNoTag(final int value) {return computeRawVarint32Size(value);}/*** Compute the number of bytes that would be needed to encode an enum field.* Caller is responsible for converting the enum value to its numeric value.*/public static int computeEnumSizeNoTag(final int value) {return computeInt32SizeNoTag(value);}/*** Compute the number of bytes that would be needed to encode an* {@code sfixed32} field.*/public static int computeSFixed32SizeNoTag(final int value) {return LITTLE_ENDIAN_32_SIZE;}/*** Compute the number of bytes that would be needed to encode an* {@code sfixed64} field.*/public static int computeSFixed64SizeNoTag(final long value) {return LITTLE_ENDIAN_64_SIZE;}/*** Compute the number of bytes that would be needed to encode an* {@code sint32} field.*/public static int computeSInt32SizeNoTag(final int value) {return computeRawVarint32Size(encodeZigZag32(value));}/*** Compute the number of bytes that would be needed to encode an* {@code sint64} field.*/public static int computeSInt64SizeNoTag(final long value) {return computeRawVarint64Size(encodeZigZag64(value));}// =================================================================/*** Internal helper that writes the current buffer to the output. The* buffer position is reset to its initial value when this returns.*/private void refreshBuffer() throws IOException {if (output == null) {// We're writing to a single buffer.throw new OutOfSpaceException();}// Since we have an output stream, this is our buffer// and buffer offset == 0output.write(buffer, 0, position);position = 0;}/*** Flushes the stream and forces any buffered bytes to be written. This* does not flush the underlying OutputStream.*/public void flush() throws IOException {if (output != null) {refreshBuffer();}}/*** If writing to a flat array, return the space left in the array.* Otherwise, throws {@code UnsupportedOperationException}.*/public int spaceLeft() {if (output == null) {return limit - position;} else {throw new UnsupportedOperationException("spaceLeft() can only be called on CodedOutputStreams that are " +"writing to a flat array.");}}/*** Verifies that {@link #spaceLeft()} returns zero. It's common to create* a byte array that is exactly big enough to hold a message, then write to* it with a {@code CodedOutputStream}. Calling {@code checkNoSpaceLeft()}* after writing verifies that the message was actually as big as expected,* which can help catch bugs.*/public void checkNoSpaceLeft() {if (spaceLeft() != 0) {throw new IllegalStateException("Did not write as much data as expected.");}}/*** If you create a CodedOutputStream around a simple flat array, you must* not attempt to write more bytes than the array has space. Otherwise,* this exception will be thrown.*/public static class OutOfSpaceException extends IOException {private static final long serialVersionUID = -6947486886997889499L;OutOfSpaceException() {super("CodedOutputStream was writing to a flat byte array and ran " +"out of space.");}}/** Write a single byte. */public void writeRawByte(final byte value) throws IOException {if (position == limit) {refreshBuffer();}buffer[position++] = value;}/** Write a single byte, represented by an integer value. */public void writeRawByte(final int value) throws IOException {writeRawByte((byte) value);}/** Write a byte string. */public void writeRawBytes(final ByteString value) throws IOException {writeRawBytes(value, 0, value.size());}/** Write an array of bytes. */public void writeRawBytes(final byte[] value) throws IOException {writeRawBytes(value, 0, value.length);}/** Write part of an array of bytes. */public void writeRawBytes(final byte[] value, int offset, int length)throws IOException {if (limit - position >= length) {// We have room in the current buffer.System.arraycopy(value, offset, buffer, position, length);position += length;} else {// Write extends past current buffer. Fill the rest of this buffer and// flush.final int bytesWritten = limit - position;System.arraycopy(value, offset, buffer, position, bytesWritten);offset += bytesWritten;length -= bytesWritten;position = limit;refreshBuffer();// Now deal with the rest.// Since we have an output stream, this is our buffer// and buffer offset == 0if (length <= limit) {// Fits in new buffer.System.arraycopy(value, offset, buffer, 0, length);position = length;} else {// Write is very big. Let's do it all at once.output.write(value, offset, length);}}}/** Write part of a byte string. */public void writeRawBytes(final ByteString value, int offset, int length)throws IOException {if (limit - position >= length) {// We have room in the current buffer.value.copyTo(buffer, offset, position, length);position += length;} else {// Write extends past current buffer. Fill the rest of this buffer and// flush.final int bytesWritten = limit - position;value.copyTo(buffer, offset, position, bytesWritten);offset += bytesWritten;length -= bytesWritten;position = limit;refreshBuffer();// Now deal with the rest.// Since we have an output stream, this is our buffer// and buffer offset == 0if (length <= limit) {// Fits in new buffer.value.copyTo(buffer, offset, 0, length);position = length;} else {// Write is very big, but we can't do it all at once without allocating// an a copy of the byte array since ByteString does not give us access// to the underlying bytes. Use the InputStream interface on the// ByteString and our buffer to copy between the two.InputStream inputStreamFrom = value.newInput();if (offset != inputStreamFrom.skip(offset)) {throw new IllegalStateException("Skip failed? Should never happen.");}// Use the buffer as the temporary buffer to avoid allocating memory.while (length > 0) {int bytesToRead = Math.min(length, limit);int bytesRead = inputStreamFrom.read(buffer, 0, bytesToRead);if (bytesRead != bytesToRead) {throw new IllegalStateException("Read failed? Should never happen");}output.write(buffer, 0, bytesRead);length -= bytesRead;}}}}/** Encode and write a tag. */public void writeTag(final int fieldNumber, final int wireType)throws IOException {writeRawVarint32(WireFormat.makeTag(fieldNumber, wireType));}/** Compute the number of bytes that would be needed to encode a tag. */public static int computeTagSize(final int fieldNumber) {return computeRawVarint32Size(WireFormat.makeTag(fieldNumber, 0));}/*** Encode and write a varint. {@code value} is treated as* unsigned, so it won't be sign-extended if negative.*/public void writeRawVarint32(int value) throws IOException {while (true) {if ((value & ~0x7F) == 0) {writeRawByte(value);return;} else {writeRawByte((value & 0x7F) | 0x80);value >>>= 7;}}}/*** Compute the number of bytes that would be needed to encode a varint.* {@code value} is treated as unsigned, so it won't be sign-extended if* negative.*/public static int computeRawVarint32Size(final int value) {if ((value & (0xffffffff << 7)) == 0) return 1;if ((value & (0xffffffff << 14)) == 0) return 2;if ((value & (0xffffffff << 21)) == 0) return 3;if ((value & (0xffffffff << 28)) == 0) return 4;return 5;}/** Encode and write a varint. */public void writeRawVarint64(long value) throws IOException {while (true) {if ((value & ~0x7FL) == 0) {writeRawByte((int)value);return;} else {writeRawByte(((int)value & 0x7F) | 0x80);value >>>= 7;}}}/** Compute the number of bytes that would be needed to encode a varint. */public static int computeRawVarint64Size(final long value) {if ((value & (0xffffffffffffffffL << 7)) == 0) return 1;if ((value & (0xffffffffffffffffL << 14)) == 0) return 2;if ((value & (0xffffffffffffffffL << 21)) == 0) return 3;if ((value & (0xffffffffffffffffL << 28)) == 0) return 4;if ((value & (0xffffffffffffffffL << 35)) == 0) return 5;if ((value & (0xffffffffffffffffL << 42)) == 0) return 6;if ((value & (0xffffffffffffffffL << 49)) == 0) return 7;if ((value & (0xffffffffffffffffL << 56)) == 0) return 8;if ((value & (0xffffffffffffffffL << 63)) == 0) return 9;return 10;}/** Write a little-endian 32-bit integer. */public void writeRawLittleEndian32(final int value) throws IOException {writeRawByte((value ) & 0xFF);writeRawByte((value >> 8) & 0xFF);writeRawByte((value >> 16) & 0xFF);writeRawByte((value >> 24) & 0xFF);}public static final int LITTLE_ENDIAN_32_SIZE = 4;/** Write a little-endian 64-bit integer. */public void writeRawLittleEndian64(final long value) throws IOException {writeRawByte((int)(value ) & 0xFF);writeRawByte((int)(value >> 8) & 0xFF);writeRawByte((int)(value >> 16) & 0xFF);writeRawByte((int)(value >> 24) & 0xFF);writeRawByte((int)(value >> 32) & 0xFF);writeRawByte((int)(value >> 40) & 0xFF);writeRawByte((int)(value >> 48) & 0xFF);writeRawByte((int)(value >> 56) & 0xFF);}public static final int LITTLE_ENDIAN_64_SIZE = 8;/*** Encode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers* into values that can be efficiently encoded with varint. (Otherwise,* negative values must be sign-extended to 64 bits to be varint encoded,* thus always taking 10 bytes on the wire.)** @param n A signed 32-bit integer.* @return An unsigned 32-bit integer, stored in a signed int because* Java has no explicit unsigned support.*/public static int encodeZigZag32(final int n) {// Note: the right-shift must be arithmeticreturn (n << 1) ^ (n >> 31);}/*** Encode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers* into values that can be efficiently encoded with varint. (Otherwise,* negative values must be sign-extended to 64 bits to be varint encoded,* thus always taking 10 bytes on the wire.)** @param n A signed 64-bit integer.* @return An unsigned 64-bit integer, stored in a signed int because* Java has no explicit unsigned support.*/public static long encodeZigZag64(final long n) {// Note: the right-shift must be arithmeticreturn (n << 1) ^ (n >> 63);}}