package com.google.protobuf;
import static com.google.protobuf.WireFormat.FIXED32_SIZE;
import static com.google.protobuf.WireFormat.FIXED64_SIZE;
import static com.google.protobuf.WireFormat.MAX_VARINT32_SIZE;
import static com.google.protobuf.WireFormat.MAX_VARINT_SIZE;
import static java.lang.Math.max;
import com.google.protobuf.Utf8.UnpairedSurrogateException;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.logging.Level;
import java.util.logging.Logger;
public abstract class CodedOutputStream extends ByteOutput {
private static final Logger logger = Logger.getLogger(CodedOutputStream.class.getName());
private static final boolean HAS_UNSAFE_ARRAY_OPERATIONS = UnsafeUtil.hasUnsafeArrayOperations();
CodedOutputStreamWriter wrapper;
@Deprecated public static final int LITTLE_ENDIAN_32_SIZE = FIXED32_SIZE;
public static final int DEFAULT_BUFFER_SIZE = 4096;
static int computePreferredBufferSize(int dataLength) {
if (dataLength > DEFAULT_BUFFER_SIZE) {
return DEFAULT_BUFFER_SIZE;
}
return dataLength;
}
public static CodedOutputStream newInstance(final OutputStream output) {
return newInstance(output, DEFAULT_BUFFER_SIZE);
}
public static CodedOutputStream newInstance(final OutputStream output, final int bufferSize) {
return new OutputStreamEncoder(output, bufferSize);
}
public static CodedOutputStream newInstance(final byte[] flatArray) {
return newInstance(flatArray, 0, flatArray.length);
}
public static CodedOutputStream newInstance(
final byte[] flatArray, final int offset, final int length) {
return new ArrayEncoder(flatArray, offset, length);
}
public static CodedOutputStream newInstance(ByteBuffer buffer) {
if (buffer.hasArray()) {
return new HeapNioEncoder(buffer);
}
if (buffer.isDirect() && !buffer.isReadOnly()) {
return UnsafeDirectNioEncoder.isSupported()
? newUnsafeInstance(buffer)
: newSafeInstance(buffer);
}
throw new IllegalArgumentException("ByteBuffer is read-only");
}
static CodedOutputStream newUnsafeInstance(ByteBuffer buffer) {
return new UnsafeDirectNioEncoder(buffer);
}
static CodedOutputStream newSafeInstance(ByteBuffer buffer) {
return new SafeDirectNioEncoder(buffer);
}
public void useDeterministicSerialization() {
serializationDeterministic = true;
}
boolean isSerializationDeterministic() {
return serializationDeterministic;
}
private boolean serializationDeterministic;
@Deprecated
public static CodedOutputStream newInstance(
ByteBuffer byteBuffer, @SuppressWarnings("unused") int unused) {
return newInstance(byteBuffer);
}
static CodedOutputStream newInstance(ByteOutput byteOutput, int bufferSize) {
if (bufferSize < 0) {
throw new IllegalArgumentException("bufferSize must be positive");
}
return new ByteOutputEncoder(byteOutput, bufferSize);
}
private CodedOutputStream() {}
public abstract void writeTag(int fieldNumber, int wireType) throws IOException;
public abstract void writeInt32(int fieldNumber, int value) throws IOException;
public abstract void writeUInt32(int fieldNumber, int value) throws IOException;
public final void writeSInt32(final int fieldNumber, final int value) throws IOException {
writeUInt32(fieldNumber, encodeZigZag32(value));
}
public abstract void writeFixed32(int fieldNumber, int value) throws IOException;
public final void writeSFixed32(final int fieldNumber, final int value) throws IOException {
writeFixed32(fieldNumber, value);
}
public final void writeInt64(final int fieldNumber, final long value) throws IOException {
writeUInt64(fieldNumber, value);
}
public abstract void writeUInt64(int fieldNumber, long value) throws IOException;
public final void writeSInt64(final int fieldNumber, final long value) throws IOException {
writeUInt64(fieldNumber, encodeZigZag64(value));
}
public abstract void writeFixed64(int fieldNumber, long value) throws IOException;
public final void writeSFixed64(final int fieldNumber, final long value) throws IOException {
writeFixed64(fieldNumber, value);
}
public final void writeFloat(final int fieldNumber, final float value) throws IOException {
writeFixed32(fieldNumber, Float.floatToRawIntBits(value));
}
public final void writeDouble(final int fieldNumber, final double value) throws IOException {
writeFixed64(fieldNumber, Double.doubleToRawLongBits(value));
}
public abstract void writeBool(int fieldNumber, boolean value) throws IOException;
public final void writeEnum(final int fieldNumber, final int value) throws IOException {
writeInt32(fieldNumber, value);
}
public abstract void writeString(int fieldNumber, String value) throws IOException;
public abstract void writeBytes(int fieldNumber, ByteString value) throws IOException;
public abstract void writeByteArray(int fieldNumber, byte[] value) throws IOException;
public abstract void writeByteArray(int fieldNumber, byte[] value, int offset, int length)
throws IOException;
public abstract void writeByteBuffer(int fieldNumber, ByteBuffer value) throws IOException;
public final void writeRawByte(final byte value) throws IOException {
write(value);
}
public final void writeRawByte(final int value) throws IOException {
write((byte) value);
}
public final void writeRawBytes(final byte[] value) throws IOException {
write(value, 0, value.length);
}
public final void writeRawBytes(final byte[] value, int offset, int length) throws IOException {
write(value, offset, length);
}
public final void writeRawBytes(final ByteString value) throws IOException {
value.writeTo(this);
}
public abstract void writeRawBytes(final ByteBuffer value) throws IOException;
public abstract void writeMessage(final int fieldNumber, final MessageLite value)
throws IOException;
abstract void writeMessage(final int fieldNumber, final MessageLite value, Schema schema)
throws IOException;
public abstract void writeMessageSetExtension(final int fieldNumber, final MessageLite value)
throws IOException;
public abstract void writeRawMessageSetExtension(final int fieldNumber, final ByteString value)
throws IOException;
public abstract void writeInt32NoTag(final int value) throws IOException;
public abstract void writeUInt32NoTag(int value) throws IOException;
public final void writeSInt32NoTag(final int value) throws IOException {
writeUInt32NoTag(encodeZigZag32(value));
}
public abstract void writeFixed32NoTag(int value) throws IOException;
public final void writeSFixed32NoTag(final int value) throws IOException {
writeFixed32NoTag(value);
}
public final void writeInt64NoTag(final long value) throws IOException {
writeUInt64NoTag(value);
}
public abstract void writeUInt64NoTag(long value) throws IOException;
public final void writeSInt64NoTag(final long value) throws IOException {
writeUInt64NoTag(encodeZigZag64(value));
}
public abstract void writeFixed64NoTag(long value) throws IOException;
public final void writeSFixed64NoTag(final long value) throws IOException {
writeFixed64NoTag(value);
}
public final void writeFloatNoTag(final float value) throws IOException {
writeFixed32NoTag(Float.floatToRawIntBits(value));
}
public final void writeDoubleNoTag(final double value) throws IOException {
writeFixed64NoTag(Double.doubleToRawLongBits(value));
}
public final void writeBoolNoTag(final boolean value) throws IOException {
write((byte) (value ? 1 : 0));
}
public final void writeEnumNoTag(final int value) throws IOException {
writeInt32NoTag(value);
}
public abstract void writeStringNoTag(String value) throws IOException;
public abstract void writeBytesNoTag(final ByteString value) throws IOException;
public final void writeByteArrayNoTag(final byte[] value) throws IOException {
writeByteArrayNoTag(value, 0, value.length);
}
public abstract void writeMessageNoTag(final MessageLite value) throws IOException;
abstract void writeMessageNoTag(final MessageLite value, Schema schema) throws IOException;
@ExperimentalApi
@Override
public abstract void write(byte value) throws IOException;
@ExperimentalApi
@Override
public abstract void write(byte[] value, int offset, int length) throws IOException;
@ExperimentalApi
@Override
public abstract void writeLazy(byte[] value, int offset, int length) throws IOException;
@Override
public abstract void write(ByteBuffer value) throws IOException;
@ExperimentalApi
@Override
public abstract void writeLazy(ByteBuffer value) throws IOException;
public static int computeInt32Size(final int fieldNumber, final int value) {
return computeTagSize(fieldNumber) + computeInt32SizeNoTag(value);
}
public static int computeUInt32Size(final int fieldNumber, final int value) {
return computeTagSize(fieldNumber) + computeUInt32SizeNoTag(value);
}
public static int computeSInt32Size(final int fieldNumber, final int value) {
return computeTagSize(fieldNumber) + computeSInt32SizeNoTag(value);
}
public static int computeFixed32Size(final int fieldNumber, final int value) {
return computeTagSize(fieldNumber) + computeFixed32SizeNoTag(value);
}
public static int computeSFixed32Size(final int fieldNumber, final int value) {
return computeTagSize(fieldNumber) + computeSFixed32SizeNoTag(value);
}
public static int computeInt64Size(final int fieldNumber, final long value) {
return computeTagSize(fieldNumber) + computeInt64SizeNoTag(value);
}
public static int computeUInt64Size(final int fieldNumber, final long value) {
return computeTagSize(fieldNumber) + computeUInt64SizeNoTag(value);
}
public static int computeSInt64Size(final int fieldNumber, final long value) {
return computeTagSize(fieldNumber) + computeSInt64SizeNoTag(value);
}
public static int computeFixed64Size(final int fieldNumber, final long value) {
return computeTagSize(fieldNumber) + computeFixed64SizeNoTag(value);
}
public static int computeSFixed64Size(final int fieldNumber, final long value) {
return computeTagSize(fieldNumber) + computeSFixed64SizeNoTag(value);
}
public static int computeFloatSize(final int fieldNumber, final float value) {
return computeTagSize(fieldNumber) + computeFloatSizeNoTag(value);
}
public static int computeDoubleSize(final int fieldNumber, final double value) {
return computeTagSize(fieldNumber) + computeDoubleSizeNoTag(value);
}
public static int computeBoolSize(final int fieldNumber, final boolean value) {
return computeTagSize(fieldNumber) + computeBoolSizeNoTag(value);
}
public static int computeEnumSize(final int fieldNumber, final int value) {
return computeTagSize(fieldNumber) + computeEnumSizeNoTag(value);
}
public static int computeStringSize(final int fieldNumber, final String value) {
return computeTagSize(fieldNumber) + computeStringSizeNoTag(value);
}
public static int computeBytesSize(final int fieldNumber, final ByteString value) {
return computeTagSize(fieldNumber) + computeBytesSizeNoTag(value);
}
public static int computeByteArraySize(final int fieldNumber, final byte[] value) {
return computeTagSize(fieldNumber) + computeByteArraySizeNoTag(value);
}
public static int computeByteBufferSize(final int fieldNumber, final ByteBuffer value) {
return computeTagSize(fieldNumber) + computeByteBufferSizeNoTag(value);
}
public static int computeLazyFieldSize(final int fieldNumber, final LazyFieldLite value) {
return computeTagSize(fieldNumber) + computeLazyFieldSizeNoTag(value);
}
public static int computeMessageSize(final int fieldNumber, final MessageLite value) {
return computeTagSize(fieldNumber) + computeMessageSizeNoTag(value);
}
static int computeMessageSize(
final int fieldNumber, final MessageLite value, final Schema schema) {
return computeTagSize(fieldNumber) + computeMessageSizeNoTag(value, schema);
}
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);
}
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);
}
public static int computeLazyFieldMessageSetExtensionSize(
final int fieldNumber, final LazyFieldLite value) {
return computeTagSize(WireFormat.MESSAGE_SET_ITEM) * 2
+ computeUInt32Size(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber)
+ computeLazyFieldSize(WireFormat.MESSAGE_SET_MESSAGE, value);
}
public static int computeTagSize(final int fieldNumber) {
return computeUInt32SizeNoTag(WireFormat.makeTag(fieldNumber, 0));
}
public static int computeInt32SizeNoTag(final int value) {
if (value >= 0) {
return computeUInt32SizeNoTag(value);
} else {
return MAX_VARINT_SIZE;
}
}
public static int computeUInt32SizeNoTag(final int value) {
if ((value & (~0 << 7)) == 0) {
return 1;
}
if ((value & (~0 << 14)) == 0) {
return 2;
}
if ((value & (~0 << 21)) == 0) {
return 3;
}
if ((value & (~0 << 28)) == 0) {
return 4;
}
return 5;
}
public static int computeSInt32SizeNoTag(final int value) {
return computeUInt32SizeNoTag(encodeZigZag32(value));
}
public static int computeFixed32SizeNoTag(@SuppressWarnings("unused") final int unused) {
return FIXED32_SIZE;
}
public static int computeSFixed32SizeNoTag(@SuppressWarnings("unused") final int unused) {
return FIXED32_SIZE;
}
public static int computeInt64SizeNoTag(final long value) {
return computeUInt64SizeNoTag(value);
}
public static int computeUInt64SizeNoTag(long value) {
if ((value & (~0L << 7)) == 0L) {
return 1;
}
if (value < 0L) {
return 10;
}
int n = 2;
if ((value & (~0L << 35)) != 0L) {
n += 4;
value >>>= 28;
}
if ((value & (~0L << 21)) != 0L) {
n += 2;
value >>>= 14;
}
if ((value & (~0L << 14)) != 0L) {
n += 1;
}
return n;
}
public static int computeSInt64SizeNoTag(final long value) {
return computeUInt64SizeNoTag(encodeZigZag64(value));
}
public static int computeFixed64SizeNoTag(@SuppressWarnings("unused") final long unused) {
return FIXED64_SIZE;
}
public static int computeSFixed64SizeNoTag(@SuppressWarnings("unused") final long unused) {
return FIXED64_SIZE;
}
public static int computeFloatSizeNoTag(@SuppressWarnings("unused") final float unused) {
return FIXED32_SIZE;
}
public static int computeDoubleSizeNoTag(@SuppressWarnings("unused") final double unused) {
return FIXED64_SIZE;
}
public static int computeBoolSizeNoTag(@SuppressWarnings("unused") final boolean unused) {
return 1;
}
public static int computeEnumSizeNoTag(final int value) {
return computeInt32SizeNoTag(value);
}
public static int computeStringSizeNoTag(final String value) {
int length;
try {
length = Utf8.encodedLength(value);
} catch (UnpairedSurrogateException e) {
final byte[] bytes = value.getBytes(Internal.UTF_8);
length = bytes.length;
}
return computeLengthDelimitedFieldSize(length);
}
public static int computeLazyFieldSizeNoTag(final LazyFieldLite value) {
return computeLengthDelimitedFieldSize(value.getSerializedSize());
}
public static int computeBytesSizeNoTag(final ByteString value) {
return computeLengthDelimitedFieldSize(value.size());
}
public static int computeByteArraySizeNoTag(final byte[] value) {
return computeLengthDelimitedFieldSize(value.length);
}
public static int computeByteBufferSizeNoTag(final ByteBuffer value) {
return computeLengthDelimitedFieldSize(value.capacity());
}
public static int computeMessageSizeNoTag(final MessageLite value) {
return computeLengthDelimitedFieldSize(value.getSerializedSize());
}
static int computeMessageSizeNoTag(final MessageLite value, final Schema schema) {
return computeLengthDelimitedFieldSize(((AbstractMessageLite) value).getSerializedSize(schema));
}
static int computeLengthDelimitedFieldSize(int fieldLength) {
return computeUInt32SizeNoTag(fieldLength) + fieldLength;
}
public static int encodeZigZag32(final int n) {
return (n << 1) ^ (n >> 31);
}
public static long encodeZigZag64(final long n) {
return (n << 1) ^ (n >> 63);
}
public abstract void flush() throws IOException;
public abstract int spaceLeft();
public final void checkNoSpaceLeft() {
if (spaceLeft() != 0) {
throw new IllegalStateException("Did not write as much data as expected.");
}
}
public static class OutOfSpaceException extends IOException {
private static final long serialVersionUID = -6947486886997889499L;
private static final String MESSAGE =
"CodedOutputStream was writing to a flat byte array and ran out of space.";
OutOfSpaceException() {
super(MESSAGE);
}
OutOfSpaceException(String explanationMessage) {
super(MESSAGE + ": " + explanationMessage);
}
OutOfSpaceException(Throwable cause) {
super(MESSAGE, cause);
}
OutOfSpaceException(String explanationMessage, Throwable cause) {
super(MESSAGE + ": " + explanationMessage, cause);
}
}
public abstract int getTotalBytesWritten();
abstract void writeByteArrayNoTag(final byte[] value, final int offset, final int length)
throws IOException;
final void inefficientWriteStringNoTag(String value, UnpairedSurrogateException cause)
throws IOException {
logger.log(
Level.WARNING,
"Converting ill-formed UTF-16. Your Protocol Buffer will not round trip correctly!",
cause);
final byte[] bytes = value.getBytes(Internal.UTF_8);
try {
writeUInt32NoTag(bytes.length);
writeLazy(bytes, 0, bytes.length);
} catch (IndexOutOfBoundsException e) {
throw new OutOfSpaceException(e);
} catch (OutOfSpaceException e) {
throw e;
}
}
@Deprecated
public final void writeGroup(final int fieldNumber, final MessageLite value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_START_GROUP);
writeGroupNoTag(value);
writeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP);
}
@Deprecated
final void writeGroup(final int fieldNumber, final MessageLite value, Schema schema)
throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_START_GROUP);
writeGroupNoTag(value, schema);
writeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP);
}
@Deprecated
public final void writeGroupNoTag(final MessageLite value) throws IOException {
value.writeTo(this);
}
@Deprecated
final void writeGroupNoTag(final MessageLite value, Schema schema) throws IOException {
schema.writeTo(value, wrapper);
}
@Deprecated
public static int computeGroupSize(final int fieldNumber, final MessageLite value) {
return computeTagSize(fieldNumber) * 2 + computeGroupSizeNoTag(value);
}
@Deprecated
static int computeGroupSize(final int fieldNumber, final MessageLite value, Schema schema) {
return computeTagSize(fieldNumber) * 2 + computeGroupSizeNoTag(value, schema);
}
@Deprecated
public static int computeGroupSizeNoTag(final MessageLite value) {
return value.getSerializedSize();
}
@Deprecated
static int computeGroupSizeNoTag(final MessageLite value, Schema schema) {
return ((AbstractMessageLite) value).getSerializedSize(schema);
}
@Deprecated
public final void writeRawVarint32(int value) throws IOException {
writeUInt32NoTag(value);
}
@Deprecated
public final void writeRawVarint64(long value) throws IOException {
writeUInt64NoTag(value);
}
@Deprecated
public static int computeRawVarint32Size(final int value) {
return computeUInt32SizeNoTag(value);
}
@Deprecated
public static int computeRawVarint64Size(long value) {
return computeUInt64SizeNoTag(value);
}
@Deprecated
public final void writeRawLittleEndian32(final int value) throws IOException {
writeFixed32NoTag(value);
}
@Deprecated
public final void writeRawLittleEndian64(final long value) throws IOException {
writeFixed64NoTag(value);
}
private static class ArrayEncoder extends CodedOutputStream {
private final byte[] buffer;
private final int offset;
private final int limit;
private int position;
ArrayEncoder(byte[] buffer, int offset, int length) {
if (buffer == null) {
throw new NullPointerException("buffer");
}
if ((offset | length | (buffer.length - (offset + length))) < 0) {
throw new IllegalArgumentException(
String.format(
"Array range is invalid. Buffer.length=%d, offset=%d, length=%d",
buffer.length, offset, length));
}
this.buffer = buffer;
this.offset = offset;
position = offset;
limit = offset + length;
}
@Override
public final void writeTag(final int fieldNumber, final int wireType) throws IOException {
writeUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType));
}
@Override
public final void writeInt32(final int fieldNumber, final int value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
writeInt32NoTag(value);
}
@Override
public final void writeUInt32(final int fieldNumber, final int value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
writeUInt32NoTag(value);
}
@Override
public final void writeFixed32(final int fieldNumber, final int value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
writeFixed32NoTag(value);
}
@Override
public final void writeUInt64(final int fieldNumber, final long value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
writeUInt64NoTag(value);
}
@Override
public final void writeFixed64(final int fieldNumber, final long value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
writeFixed64NoTag(value);
}
@Override
public final void writeBool(final int fieldNumber, final boolean value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
write((byte) (value ? 1 : 0));
}
@Override
public final void writeString(final int fieldNumber, final String value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
writeStringNoTag(value);
}
@Override
public final void writeBytes(final int fieldNumber, final ByteString value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
writeBytesNoTag(value);
}
@Override
public final void writeByteArray(final int fieldNumber, final byte[] value) throws IOException {
writeByteArray(fieldNumber, value, 0, value.length);
}
@Override
public final void writeByteArray(
final int fieldNumber, final byte[] value, final int offset, final int length)
throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
writeByteArrayNoTag(value, offset, length);
}
@Override
public final void writeByteBuffer(final int fieldNumber, final ByteBuffer value)
throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
writeUInt32NoTag(value.capacity());
writeRawBytes(value);
}
@Override
public final void writeBytesNoTag(final ByteString value) throws IOException {
writeUInt32NoTag(value.size());
value.writeTo(this);
}
@Override
public final void writeByteArrayNoTag(final byte[] value, int offset, int length)
throws IOException {
writeUInt32NoTag(length);
write(value, offset, length);
}
@Override
public final void writeRawBytes(final ByteBuffer value) throws IOException {
if (value.hasArray()) {
write(value.array(), value.arrayOffset(), value.capacity());
} else {
ByteBuffer duplicated = value.duplicate();
duplicated.clear();
write(duplicated);
}
}
@Override
public final void writeMessage(final int fieldNumber, final MessageLite value)
throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
writeMessageNoTag(value);
}
@Override
final void writeMessage(final int fieldNumber, final MessageLite value, Schema schema)
throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
writeUInt32NoTag(((AbstractMessageLite) value).getSerializedSize(schema));
schema.writeTo(value, wrapper);
}
@Override
public final 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);
}
@Override
public final 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);
}
@Override
public final void writeMessageNoTag(final MessageLite value) throws IOException {
writeUInt32NoTag(value.getSerializedSize());
value.writeTo(this);
}
@Override
final void writeMessageNoTag(final MessageLite value, Schema schema) throws IOException {
writeUInt32NoTag(((AbstractMessageLite) value).getSerializedSize(schema));
schema.writeTo(value, wrapper);
}
@Override
public final void write(byte value) throws IOException {
try {
buffer[position++] = value;
} catch (IndexOutOfBoundsException e) {
throw new OutOfSpaceException(
String.format("Pos: %d, limit: %d, len: %d", position, limit, 1), e);
}
}
@Override
public final void writeInt32NoTag(int value) throws IOException {
if (value >= 0) {
writeUInt32NoTag(value);
} else {
writeUInt64NoTag(value);
}
}
@Override
public final void writeUInt32NoTag(int value) throws IOException {
if (HAS_UNSAFE_ARRAY_OPERATIONS
&& !Android.isOnAndroidDevice()
&& spaceLeft() >= MAX_VARINT32_SIZE) {
if ((value & ~0x7F) == 0) {
UnsafeUtil.putByte(buffer, position++, (byte) value);
return;
}
UnsafeUtil.putByte(buffer, position++, (byte) (value | 0x80));
value >>>= 7;
if ((value & ~0x7F) == 0) {
UnsafeUtil.putByte(buffer, position++, (byte) value);
return;
}
UnsafeUtil.putByte(buffer, position++, (byte) (value | 0x80));
value >>>= 7;
if ((value & ~0x7F) == 0) {
UnsafeUtil.putByte(buffer, position++, (byte) value);
return;
}
UnsafeUtil.putByte(buffer, position++, (byte) (value | 0x80));
value >>>= 7;
if ((value & ~0x7F) == 0) {
UnsafeUtil.putByte(buffer, position++, (byte) value);
return;
}
UnsafeUtil.putByte(buffer, position++, (byte) (value | 0x80));
value >>>= 7;
UnsafeUtil.putByte(buffer, position++, (byte) value);
} else {
try {
while (true) {
if ((value & ~0x7F) == 0) {
buffer[position++] = (byte) value;
return;
} else {
buffer[position++] = (byte) ((value & 0x7F) | 0x80);
value >>>= 7;
}
}
} catch (IndexOutOfBoundsException e) {
throw new OutOfSpaceException(
String.format("Pos: %d, limit: %d, len: %d", position, limit, 1), e);
}
}
}
@Override
public final void writeFixed32NoTag(int value) throws IOException {
try {
buffer[position++] = (byte) (value & 0xFF);
buffer[position++] = (byte) ((value >> 8) & 0xFF);
buffer[position++] = (byte) ((value >> 16) & 0xFF);
buffer[position++] = (byte) ((value >> 24) & 0xFF);
} catch (IndexOutOfBoundsException e) {
throw new OutOfSpaceException(
String.format("Pos: %d, limit: %d, len: %d", position, limit, 1), e);
}
}
@Override
public final void writeUInt64NoTag(long value) throws IOException {
if (HAS_UNSAFE_ARRAY_OPERATIONS && spaceLeft() >= MAX_VARINT_SIZE) {
while (true) {
if ((value & ~0x7FL) == 0) {
UnsafeUtil.putByte(buffer, position++, (byte) value);
return;
} else {
UnsafeUtil.putByte(buffer, position++, (byte) (((int) value & 0x7F) | 0x80));
value >>>= 7;
}
}
} else {
try {
while (true) {
if ((value & ~0x7FL) == 0) {
buffer[position++] = (byte) value;
return;
} else {
buffer[position++] = (byte) (((int) value & 0x7F) | 0x80);
value >>>= 7;
}
}
} catch (IndexOutOfBoundsException e) {
throw new OutOfSpaceException(
String.format("Pos: %d, limit: %d, len: %d", position, limit, 1), e);
}
}
}
@Override
public final void writeFixed64NoTag(long value) throws IOException {
try {
buffer[position++] = (byte) ((int) (value) & 0xFF);
buffer[position++] = (byte) ((int) (value >> 8) & 0xFF);
buffer[position++] = (byte) ((int) (value >> 16) & 0xFF);
buffer[position++] = (byte) ((int) (value >> 24) & 0xFF);
buffer[position++] = (byte) ((int) (value >> 32) & 0xFF);
buffer[position++] = (byte) ((int) (value >> 40) & 0xFF);
buffer[position++] = (byte) ((int) (value >> 48) & 0xFF);
buffer[position++] = (byte) ((int) (value >> 56) & 0xFF);
} catch (IndexOutOfBoundsException e) {
throw new OutOfSpaceException(
String.format("Pos: %d, limit: %d, len: %d", position, limit, 1), e);
}
}
@Override
public final void write(byte[] value, int offset, int length) throws IOException {
try {
System.arraycopy(value, offset, buffer, position, length);
position += length;
} catch (IndexOutOfBoundsException e) {
throw new OutOfSpaceException(
String.format("Pos: %d, limit: %d, len: %d", position, limit, length), e);
}
}
@Override
public final void writeLazy(byte[] value, int offset, int length) throws IOException {
write(value, offset, length);
}
@Override
public final void write(ByteBuffer value) throws IOException {
final int length = value.remaining();
try {
value.get(buffer, position, length);
position += length;
} catch (IndexOutOfBoundsException e) {
throw new OutOfSpaceException(
String.format("Pos: %d, limit: %d, len: %d", position, limit, length), e);
}
}
@Override
public final void writeLazy(ByteBuffer value) throws IOException {
write(value);
}
@Override
public final void writeStringNoTag(String value) throws IOException {
final int oldPosition = position;
try {
final int maxLength = value.length() * Utf8.MAX_BYTES_PER_CHAR;
final int maxLengthVarIntSize = computeUInt32SizeNoTag(maxLength);
final int minLengthVarIntSize = computeUInt32SizeNoTag(value.length());
if (minLengthVarIntSize == maxLengthVarIntSize) {
position = oldPosition + minLengthVarIntSize;
int newPosition = Utf8.encode(value, buffer, position, spaceLeft());
position = oldPosition;
int length = newPosition - oldPosition - minLengthVarIntSize;
writeUInt32NoTag(length);
position = newPosition;
} else {
int length = Utf8.encodedLength(value);
writeUInt32NoTag(length);
position = Utf8.encode(value, buffer, position, spaceLeft());
}
} catch (UnpairedSurrogateException e) {
position = oldPosition;
inefficientWriteStringNoTag(value, e);
} catch (IndexOutOfBoundsException e) {
throw new OutOfSpaceException(e);
}
}
@Override
public void flush() {
}
@Override
public final int spaceLeft() {
return limit - position;
}
@Override
public final int getTotalBytesWritten() {
return position - offset;
}
}
private static final class HeapNioEncoder extends ArrayEncoder {
private final ByteBuffer byteBuffer;
private int initialPosition;
HeapNioEncoder(ByteBuffer byteBuffer) {
super(
byteBuffer.array(),
byteBuffer.arrayOffset() + byteBuffer.position(),
byteBuffer.remaining());
this.byteBuffer = byteBuffer;
this.initialPosition = byteBuffer.position();
}
@Override
public void flush() {
byteBuffer.position(initialPosition + getTotalBytesWritten());
}
}
private static final class SafeDirectNioEncoder extends CodedOutputStream {
private final ByteBuffer originalBuffer;
private final ByteBuffer buffer;
private final int initialPosition;
SafeDirectNioEncoder(ByteBuffer buffer) {
this.originalBuffer = buffer;
this.buffer = buffer.duplicate().order(ByteOrder.LITTLE_ENDIAN);
initialPosition = buffer.position();
}
@Override
public void writeTag(final int fieldNumber, final int wireType) throws IOException {
writeUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType));
}
@Override
public void writeInt32(final int fieldNumber, final int value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
writeInt32NoTag(value);
}
@Override
public void writeUInt32(final int fieldNumber, final int value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
writeUInt32NoTag(value);
}
@Override
public void writeFixed32(final int fieldNumber, final int value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
writeFixed32NoTag(value);
}
@Override
public void writeUInt64(final int fieldNumber, final long value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
writeUInt64NoTag(value);
}
@Override
public void writeFixed64(final int fieldNumber, final long value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
writeFixed64NoTag(value);
}
@Override
public void writeBool(final int fieldNumber, final boolean value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
write((byte) (value ? 1 : 0));
}
@Override
public void writeString(final int fieldNumber, final String value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
writeStringNoTag(value);
}
@Override
public void writeBytes(final int fieldNumber, final ByteString value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
writeBytesNoTag(value);
}
@Override
public void writeByteArray(final int fieldNumber, final byte[] value) throws IOException {
writeByteArray(fieldNumber, value, 0, value.length);
}
@Override
public void writeByteArray(
final int fieldNumber, final byte[] value, final int offset, final int length)
throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
writeByteArrayNoTag(value, offset, length);
}
@Override
public void writeByteBuffer(final int fieldNumber, final ByteBuffer value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
writeUInt32NoTag(value.capacity());
writeRawBytes(value);
}
@Override
public void writeMessage(final int fieldNumber, final MessageLite value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
writeMessageNoTag(value);
}
@Override
void writeMessage(final int fieldNumber, final MessageLite value, Schema schema)
throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
writeMessageNoTag(value, schema);
}
@Override
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);
}
@Override
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);
}
@Override
public void writeMessageNoTag(final MessageLite value) throws IOException {
writeUInt32NoTag(value.getSerializedSize());
value.writeTo(this);
}
@Override
void writeMessageNoTag(final MessageLite value, Schema schema) throws IOException {
writeUInt32NoTag(((AbstractMessageLite) value).getSerializedSize(schema));
schema.writeTo(value, wrapper);
}
@Override
public void write(byte value) throws IOException {
try {
buffer.put(value);
} catch (BufferOverflowException e) {
throw new OutOfSpaceException(e);
}
}
@Override
public void writeBytesNoTag(final ByteString value) throws IOException {
writeUInt32NoTag(value.size());
value.writeTo(this);
}
@Override
public void writeByteArrayNoTag(final byte[] value, int offset, int length) throws IOException {
writeUInt32NoTag(length);
write(value, offset, length);
}
@Override
public void writeRawBytes(final ByteBuffer value) throws IOException {
if (value.hasArray()) {
write(value.array(), value.arrayOffset(), value.capacity());
} else {
ByteBuffer duplicated = value.duplicate();
duplicated.clear();
write(duplicated);
}
}
@Override
public void writeInt32NoTag(int value) throws IOException {
if (value >= 0) {
writeUInt32NoTag(value);
} else {
writeUInt64NoTag(value);
}
}
@Override
public void writeUInt32NoTag(int value) throws IOException {
try {
while (true) {
if ((value & ~0x7F) == 0) {
buffer.put((byte) value);
return;
} else {
buffer.put((byte) ((value & 0x7F) | 0x80));
value >>>= 7;
}
}
} catch (BufferOverflowException e) {
throw new OutOfSpaceException(e);
}
}
@Override
public void writeFixed32NoTag(int value) throws IOException {
try {
buffer.putInt(value);
} catch (BufferOverflowException e) {
throw new OutOfSpaceException(e);
}
}
@Override
public void writeUInt64NoTag(long value) throws IOException {
try {
while (true) {
if ((value & ~0x7FL) == 0) {
buffer.put((byte) value);
return;
} else {
buffer.put((byte) (((int) value & 0x7F) | 0x80));
value >>>= 7;
}
}
} catch (BufferOverflowException e) {
throw new OutOfSpaceException(e);
}
}
@Override
public void writeFixed64NoTag(long value) throws IOException {
try {
buffer.putLong(value);
} catch (BufferOverflowException e) {
throw new OutOfSpaceException(e);
}
}
@Override
public void write(byte[] value, int offset, int length) throws IOException {
try {
buffer.put(value, offset, length);
} catch (IndexOutOfBoundsException e) {
throw new OutOfSpaceException(e);
} catch (BufferOverflowException e) {
throw new OutOfSpaceException(e);
}
}
@Override
public void writeLazy(byte[] value, int offset, int length) throws IOException {
write(value, offset, length);
}
@Override
public void write(ByteBuffer value) throws IOException {
try {
buffer.put(value);
} catch (BufferOverflowException e) {
throw new OutOfSpaceException(e);
}
}
@Override
public void writeLazy(ByteBuffer value) throws IOException {
write(value);
}
@Override
public void writeStringNoTag(String value) throws IOException {
final int startPos = buffer.position();
try {
final int maxEncodedSize = value.length() * Utf8.MAX_BYTES_PER_CHAR;
final int maxLengthVarIntSize = computeUInt32SizeNoTag(maxEncodedSize);
final int minLengthVarIntSize = computeUInt32SizeNoTag(value.length());
if (minLengthVarIntSize == maxLengthVarIntSize) {
final int startOfBytes = buffer.position() + minLengthVarIntSize;
buffer.position(startOfBytes);
encode(value);
int endOfBytes = buffer.position();
buffer.position(startPos);
writeUInt32NoTag(endOfBytes - startOfBytes);
buffer.position(endOfBytes);
} else {
final int length = Utf8.encodedLength(value);
writeUInt32NoTag(length);
encode(value);
}
} catch (UnpairedSurrogateException e) {
buffer.position(startPos);
inefficientWriteStringNoTag(value, e);
} catch (IllegalArgumentException e) {
throw new OutOfSpaceException(e);
}
}
@Override
public void flush() {
originalBuffer.position(buffer.position());
}
@Override
public int spaceLeft() {
return buffer.remaining();
}
@Override
public int getTotalBytesWritten() {
return buffer.position() - initialPosition;
}
private void encode(String value) throws IOException {
try {
Utf8.encodeUtf8(value, buffer);
} catch (IndexOutOfBoundsException e) {
throw new OutOfSpaceException(e);
}
}
}
private static final class UnsafeDirectNioEncoder extends CodedOutputStream {
private final ByteBuffer originalBuffer;
private final ByteBuffer buffer;
private final long address;
private final long initialPosition;
private final long limit;
private final long oneVarintLimit;
private long position;
UnsafeDirectNioEncoder(ByteBuffer buffer) {
this.originalBuffer = buffer;
this.buffer = buffer.duplicate().order(ByteOrder.LITTLE_ENDIAN);
address = UnsafeUtil.addressOffset(buffer);
initialPosition = address + buffer.position();
limit = address + buffer.limit();
oneVarintLimit = limit - MAX_VARINT_SIZE;
position = initialPosition;
}
static boolean isSupported() {
return UnsafeUtil.hasUnsafeByteBufferOperations();
}
@Override
public void writeTag(int fieldNumber, int wireType) throws IOException {
writeUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType));
}
@Override
public void writeInt32(int fieldNumber, int value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
writeInt32NoTag(value);
}
@Override
public void writeUInt32(int fieldNumber, int value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
writeUInt32NoTag(value);
}
@Override
public void writeFixed32(int fieldNumber, int value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
writeFixed32NoTag(value);
}
@Override
public void writeUInt64(int fieldNumber, long value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
writeUInt64NoTag(value);
}
@Override
public void writeFixed64(int fieldNumber, long value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
writeFixed64NoTag(value);
}
@Override
public void writeBool(int fieldNumber, boolean value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
write((byte) (value ? 1 : 0));
}
@Override
public void writeString(int fieldNumber, String value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
writeStringNoTag(value);
}
@Override
public void writeBytes(int fieldNumber, ByteString value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
writeBytesNoTag(value);
}
@Override
public void writeByteArray(int fieldNumber, byte[] value) throws IOException {
writeByteArray(fieldNumber, value, 0, value.length);
}
@Override
public void writeByteArray(int fieldNumber, byte[] value, int offset, int length)
throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
writeByteArrayNoTag(value, offset, length);
}
@Override
public void writeByteBuffer(int fieldNumber, ByteBuffer value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
writeUInt32NoTag(value.capacity());
writeRawBytes(value);
}
@Override
public void writeMessage(int fieldNumber, MessageLite value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
writeMessageNoTag(value);
}
@Override
void writeMessage(int fieldNumber, MessageLite value, Schema schema) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
writeMessageNoTag(value, schema);
}
@Override
public void writeMessageSetExtension(int fieldNumber, 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);
}
@Override
public void writeRawMessageSetExtension(int fieldNumber, 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);
}
@Override
public void writeMessageNoTag(MessageLite value) throws IOException {
writeUInt32NoTag(value.getSerializedSize());
value.writeTo(this);
}
@Override
void writeMessageNoTag(MessageLite value, Schema schema) throws IOException {
writeUInt32NoTag(((AbstractMessageLite) value).getSerializedSize(schema));
schema.writeTo(value, wrapper);
}
@Override
public void write(byte value) throws IOException {
if (position >= limit) {
throw new OutOfSpaceException(
String.format("Pos: %d, limit: %d, len: %d", position, limit, 1));
}
UnsafeUtil.putByte(position++, value);
}
@Override
public void writeBytesNoTag(ByteString value) throws IOException {
writeUInt32NoTag(value.size());
value.writeTo(this);
}
@Override
public void writeByteArrayNoTag(byte[] value, int offset, int length) throws IOException {
writeUInt32NoTag(length);
write(value, offset, length);
}
@Override
public void writeRawBytes(ByteBuffer value) throws IOException {
if (value.hasArray()) {
write(value.array(), value.arrayOffset(), value.capacity());
} else {
ByteBuffer duplicated = value.duplicate();
duplicated.clear();
write(duplicated);
}
}
@Override
public void writeInt32NoTag(int value) throws IOException {
if (value >= 0) {
writeUInt32NoTag(value);
} else {
writeUInt64NoTag(value);
}
}
@Override
public void writeUInt32NoTag(int value) throws IOException {
if (position <= oneVarintLimit) {
while (true) {
if ((value & ~0x7F) == 0) {
UnsafeUtil.putByte(position++, (byte) value);
return;
} else {
UnsafeUtil.putByte(position++, (byte) ((value & 0x7F) | 0x80));
value >>>= 7;
}
}
} else {
while (position < limit) {
if ((value & ~0x7F) == 0) {
UnsafeUtil.putByte(position++, (byte) value);
return;
} else {
UnsafeUtil.putByte(position++, (byte) ((value & 0x7F) | 0x80));
value >>>= 7;
}
}
throw new OutOfSpaceException(
String.format("Pos: %d, limit: %d, len: %d", position, limit, 1));
}
}
@Override
public void writeFixed32NoTag(int value) throws IOException {
buffer.putInt(bufferPos(position), value);
position += FIXED32_SIZE;
}
@Override
public void writeUInt64NoTag(long value) throws IOException {
if (position <= oneVarintLimit) {
while (true) {
if ((value & ~0x7FL) == 0) {
UnsafeUtil.putByte(position++, (byte) value);
return;
} else {
UnsafeUtil.putByte(position++, (byte) (((int) value & 0x7F) | 0x80));
value >>>= 7;
}
}
} else {
while (position < limit) {
if ((value & ~0x7FL) == 0) {
UnsafeUtil.putByte(position++, (byte) value);
return;
} else {
UnsafeUtil.putByte(position++, (byte) (((int) value & 0x7F) | 0x80));
value >>>= 7;
}
}
throw new OutOfSpaceException(
String.format("Pos: %d, limit: %d, len: %d", position, limit, 1));
}
}
@Override
public void writeFixed64NoTag(long value) throws IOException {
buffer.putLong(bufferPos(position), value);
position += FIXED64_SIZE;
}
@Override
public void write(byte[] value, int offset, int length) throws IOException {
if (value == null
|| offset < 0
|| length < 0
|| (value.length - length) < offset
|| (limit - length) < position) {
if (value == null) {
throw new NullPointerException("value");
}
throw new OutOfSpaceException(
String.format("Pos: %d, limit: %d, len: %d", position, limit, length));
}
UnsafeUtil.copyMemory(value, offset, position, length);
position += length;
}
@Override
public void writeLazy(byte[] value, int offset, int length) throws IOException {
write(value, offset, length);
}
@Override
public void write(ByteBuffer value) throws IOException {
try {
int length = value.remaining();
repositionBuffer(position);
buffer.put(value);
position += length;
} catch (BufferOverflowException e) {
throw new OutOfSpaceException(e);
}
}
@Override
public void writeLazy(ByteBuffer value) throws IOException {
write(value);
}
@Override
public void writeStringNoTag(String value) throws IOException {
long prevPos = position;
try {
int maxEncodedSize = value.length() * Utf8.MAX_BYTES_PER_CHAR;
int maxLengthVarIntSize = computeUInt32SizeNoTag(maxEncodedSize);
int minLengthVarIntSize = computeUInt32SizeNoTag(value.length());
if (minLengthVarIntSize == maxLengthVarIntSize) {
int stringStart = bufferPos(position) + minLengthVarIntSize;
buffer.position(stringStart);
Utf8.encodeUtf8(value, buffer);
int length = buffer.position() - stringStart;
writeUInt32NoTag(length);
position += length;
} else {
int length = Utf8.encodedLength(value);
writeUInt32NoTag(length);
repositionBuffer(position);
Utf8.encodeUtf8(value, buffer);
position += length;
}
} catch (UnpairedSurrogateException e) {
position = prevPos;
repositionBuffer(position);
inefficientWriteStringNoTag(value, e);
} catch (IllegalArgumentException e) {
throw new OutOfSpaceException(e);
} catch (IndexOutOfBoundsException e) {
throw new OutOfSpaceException(e);
}
}
@Override
public void flush() {
originalBuffer.position(bufferPos(position));
}
@Override
public int spaceLeft() {
return (int) (limit - position);
}
@Override
public int getTotalBytesWritten() {
return (int) (position - initialPosition);
}
private void repositionBuffer(long pos) {
buffer.position(bufferPos(pos));
}
private int bufferPos(long pos) {
return (int) (pos - address);
}
}
private abstract static class AbstractBufferedEncoder extends CodedOutputStream {
final byte[] buffer;
final int limit;
int position;
int totalBytesWritten;
AbstractBufferedEncoder(int bufferSize) {
if (bufferSize < 0) {
throw new IllegalArgumentException("bufferSize must be >= 0");
}
this.buffer = new byte[max(bufferSize, MAX_VARINT_SIZE * 2)];
this.limit = buffer.length;
}
@Override
public final int spaceLeft() {
throw new UnsupportedOperationException(
"spaceLeft() can only be called on CodedOutputStreams that are "
+ "writing to a flat array or ByteBuffer.");
}
@Override
public final int getTotalBytesWritten() {
return totalBytesWritten;
}
final void buffer(byte value) {
buffer[position++] = value;
totalBytesWritten++;
}
final void bufferTag(final int fieldNumber, final int wireType) {
bufferUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType));
}
final void bufferInt32NoTag(final int value) {
if (value >= 0) {
bufferUInt32NoTag(value);
} else {
bufferUInt64NoTag(value);
}
}
final void bufferUInt32NoTag(int value) {
if (HAS_UNSAFE_ARRAY_OPERATIONS) {
final long originalPos = position;
while (true) {
if ((value & ~0x7F) == 0) {
UnsafeUtil.putByte(buffer, position++, (byte) value);
break;
} else {
UnsafeUtil.putByte(buffer, position++, (byte) ((value & 0x7F) | 0x80));
value >>>= 7;
}
}
int delta = (int) (position - originalPos);
totalBytesWritten += delta;
} else {
while (true) {
if ((value & ~0x7F) == 0) {
buffer[position++] = (byte) value;
totalBytesWritten++;
return;
} else {
buffer[position++] = (byte) ((value & 0x7F) | 0x80);
totalBytesWritten++;
value >>>= 7;
}
}
}
}
final void bufferUInt64NoTag(long value) {
if (HAS_UNSAFE_ARRAY_OPERATIONS) {
final long originalPos = position;
while (true) {
if ((value & ~0x7FL) == 0) {
UnsafeUtil.putByte(buffer, position++, (byte) value);
break;
} else {
UnsafeUtil.putByte(buffer, position++, (byte) (((int) value & 0x7F) | 0x80));
value >>>= 7;
}
}
int delta = (int) (position - originalPos);
totalBytesWritten += delta;
} else {
while (true) {
if ((value & ~0x7FL) == 0) {
buffer[position++] = (byte) value;
totalBytesWritten++;
return;
} else {
buffer[position++] = (byte) (((int) value & 0x7F) | 0x80);
totalBytesWritten++;
value >>>= 7;
}
}
}
}
final void bufferFixed32NoTag(int value) {
buffer[position++] = (byte) (value & 0xFF);
buffer[position++] = (byte) ((value >> 8) & 0xFF);
buffer[position++] = (byte) ((value >> 16) & 0xFF);
buffer[position++] = (byte) ((value >> 24) & 0xFF);
totalBytesWritten += FIXED32_SIZE;
}
final void bufferFixed64NoTag(long value) {
buffer[position++] = (byte) (value & 0xFF);
buffer[position++] = (byte) ((value >> 8) & 0xFF);
buffer[position++] = (byte) ((value >> 16) & 0xFF);
buffer[position++] = (byte) ((value >> 24) & 0xFF);
buffer[position++] = (byte) ((int) (value >> 32) & 0xFF);
buffer[position++] = (byte) ((int) (value >> 40) & 0xFF);
buffer[position++] = (byte) ((int) (value >> 48) & 0xFF);
buffer[position++] = (byte) ((int) (value >> 56) & 0xFF);
totalBytesWritten += FIXED64_SIZE;
}
}
private static final class ByteOutputEncoder extends AbstractBufferedEncoder {
private final ByteOutput out;
ByteOutputEncoder(ByteOutput out, int bufferSize) {
super(bufferSize);
if (out == null) {
throw new NullPointerException("out");
}
this.out = out;
}
@Override
public void writeTag(final int fieldNumber, final int wireType) throws IOException {
writeUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType));
}
@Override
public void writeInt32(final int fieldNumber, final int value) throws IOException {
flushIfNotAvailable(MAX_VARINT_SIZE * 2);
bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
bufferInt32NoTag(value);
}
@Override
public void writeUInt32(final int fieldNumber, final int value) throws IOException {
flushIfNotAvailable(MAX_VARINT_SIZE * 2);
bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
bufferUInt32NoTag(value);
}
@Override
public void writeFixed32(final int fieldNumber, final int value) throws IOException {
flushIfNotAvailable(MAX_VARINT_SIZE + FIXED32_SIZE);
bufferTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
bufferFixed32NoTag(value);
}
@Override
public void writeUInt64(final int fieldNumber, final long value) throws IOException {
flushIfNotAvailable(MAX_VARINT_SIZE * 2);
bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
bufferUInt64NoTag(value);
}
@Override
public void writeFixed64(final int fieldNumber, final long value) throws IOException {
flushIfNotAvailable(MAX_VARINT_SIZE + FIXED64_SIZE);
bufferTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
bufferFixed64NoTag(value);
}
@Override
public void writeBool(final int fieldNumber, final boolean value) throws IOException {
flushIfNotAvailable(MAX_VARINT_SIZE + 1);
bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
buffer((byte) (value ? 1 : 0));
}
@Override
public void writeString(final int fieldNumber, final String value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
writeStringNoTag(value);
}
@Override
public void writeBytes(final int fieldNumber, final ByteString value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
writeBytesNoTag(value);
}
@Override
public void writeByteArray(final int fieldNumber, final byte[] value) throws IOException {
writeByteArray(fieldNumber, value, 0, value.length);
}
@Override
public void writeByteArray(
final int fieldNumber, final byte[] value, final int offset, final int length)
throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
writeByteArrayNoTag(value, offset, length);
}
@Override
public void writeByteBuffer(final int fieldNumber, final ByteBuffer value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
writeUInt32NoTag(value.capacity());
writeRawBytes(value);
}
@Override
public void writeBytesNoTag(final ByteString value) throws IOException {
writeUInt32NoTag(value.size());
value.writeTo(this);
}
@Override
public void writeByteArrayNoTag(final byte[] value, int offset, int length) throws IOException {
writeUInt32NoTag(length);
write(value, offset, length);
}
@Override
public void writeRawBytes(final ByteBuffer value) throws IOException {
if (value.hasArray()) {
write(value.array(), value.arrayOffset(), value.capacity());
} else {
ByteBuffer duplicated = value.duplicate();
duplicated.clear();
write(duplicated);
}
}
@Override
public void writeMessage(final int fieldNumber, final MessageLite value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
writeMessageNoTag(value);
}
@Override
void writeMessage(final int fieldNumber, final MessageLite value, Schema schema)
throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
writeMessageNoTag(value, schema);
}
@Override
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);
}
@Override
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);
}
@Override
public void writeMessageNoTag(final MessageLite value) throws IOException {
writeUInt32NoTag(value.getSerializedSize());
value.writeTo(this);
}
@Override
void writeMessageNoTag(final MessageLite value, Schema schema) throws IOException {
writeUInt32NoTag(((AbstractMessageLite) value).getSerializedSize(schema));
schema.writeTo(value, wrapper);
}
@Override
public void write(byte value) throws IOException {
if (position == limit) {
doFlush();
}
buffer(value);
}
@Override
public void writeInt32NoTag(int value) throws IOException {
if (value >= 0) {
writeUInt32NoTag(value);
} else {
writeUInt64NoTag(value);
}
}
@Override
public void writeUInt32NoTag(int value) throws IOException {
flushIfNotAvailable(MAX_VARINT32_SIZE);
bufferUInt32NoTag(value);
}
@Override
public void writeFixed32NoTag(final int value) throws IOException {
flushIfNotAvailable(FIXED32_SIZE);
bufferFixed32NoTag(value);
}
@Override
public void writeUInt64NoTag(long value) throws IOException {
flushIfNotAvailable(MAX_VARINT_SIZE);
bufferUInt64NoTag(value);
}
@Override
public void writeFixed64NoTag(final long value) throws IOException {
flushIfNotAvailable(FIXED64_SIZE);
bufferFixed64NoTag(value);
}
@Override
public void writeStringNoTag(String value) throws IOException {
final int maxLength = value.length() * Utf8.MAX_BYTES_PER_CHAR;
final int maxLengthVarIntSize = computeUInt32SizeNoTag(maxLength);
if (maxLengthVarIntSize + maxLength > limit) {
final byte[] encodedBytes = new byte[maxLength];
int actualLength = Utf8.encode(value, encodedBytes, 0, maxLength);
writeUInt32NoTag(actualLength);
writeLazy(encodedBytes, 0, actualLength);
return;
}
if (maxLengthVarIntSize + maxLength > limit - position) {
doFlush();
}
final int oldPosition = position;
try {
final int minLengthVarIntSize = computeUInt32SizeNoTag(value.length());
if (minLengthVarIntSize == maxLengthVarIntSize) {
position = oldPosition + minLengthVarIntSize;
int newPosition = Utf8.encode(value, buffer, position, limit - position);
position = oldPosition;
int length = newPosition - oldPosition - minLengthVarIntSize;
bufferUInt32NoTag(length);
position = newPosition;
totalBytesWritten += length;
} else {
int length = Utf8.encodedLength(value);
bufferUInt32NoTag(length);
position = Utf8.encode(value, buffer, position, length);
totalBytesWritten += length;
}
} catch (UnpairedSurrogateException e) {
totalBytesWritten -= position - oldPosition;
position = oldPosition;
inefficientWriteStringNoTag(value, e);
} catch (IndexOutOfBoundsException e) {
throw new OutOfSpaceException(e);
}
}
@Override
public void flush() throws IOException {
if (position > 0) {
doFlush();
}
}
@Override
public void write(byte[] value, int offset, int length) throws IOException {
flush();
out.write(value, offset, length);
totalBytesWritten += length;
}
@Override
public void writeLazy(byte[] value, int offset, int length) throws IOException {
flush();
out.writeLazy(value, offset, length);
totalBytesWritten += length;
}
@Override
public void write(ByteBuffer value) throws IOException {
flush();
int length = value.remaining();
out.write(value);
totalBytesWritten += length;
}
@Override
public void writeLazy(ByteBuffer value) throws IOException {
flush();
int length = value.remaining();
out.writeLazy(value);
totalBytesWritten += length;
}
private void flushIfNotAvailable(int requiredSize) throws IOException {
if (limit - position < requiredSize) {
doFlush();
}
}
private void doFlush() throws IOException {
out.write(buffer, 0, position);
position = 0;
}
}
private static final class OutputStreamEncoder extends AbstractBufferedEncoder {
private final OutputStream out;
OutputStreamEncoder(OutputStream out, int bufferSize) {
super(bufferSize);
if (out == null) {
throw new NullPointerException("out");
}
this.out = out;
}
@Override
public void writeTag(final int fieldNumber, final int wireType) throws IOException {
writeUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType));
}
@Override
public void writeInt32(final int fieldNumber, final int value) throws IOException {
flushIfNotAvailable(MAX_VARINT_SIZE * 2);
bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
bufferInt32NoTag(value);
}
@Override
public void writeUInt32(final int fieldNumber, final int value) throws IOException {
flushIfNotAvailable(MAX_VARINT_SIZE * 2);
bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
bufferUInt32NoTag(value);
}
@Override
public void writeFixed32(final int fieldNumber, final int value) throws IOException {
flushIfNotAvailable(MAX_VARINT_SIZE + FIXED32_SIZE);
bufferTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
bufferFixed32NoTag(value);
}
@Override
public void writeUInt64(final int fieldNumber, final long value) throws IOException {
flushIfNotAvailable(MAX_VARINT_SIZE * 2);
bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
bufferUInt64NoTag(value);
}
@Override
public void writeFixed64(final int fieldNumber, final long value) throws IOException {
flushIfNotAvailable(MAX_VARINT_SIZE + FIXED64_SIZE);
bufferTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
bufferFixed64NoTag(value);
}
@Override
public void writeBool(final int fieldNumber, final boolean value) throws IOException {
flushIfNotAvailable(MAX_VARINT_SIZE + 1);
bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
buffer((byte) (value ? 1 : 0));
}
@Override
public void writeString(final int fieldNumber, final String value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
writeStringNoTag(value);
}
@Override
public void writeBytes(final int fieldNumber, final ByteString value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
writeBytesNoTag(value);
}
@Override
public void writeByteArray(final int fieldNumber, final byte[] value) throws IOException {
writeByteArray(fieldNumber, value, 0, value.length);
}
@Override
public void writeByteArray(
final int fieldNumber, final byte[] value, final int offset, final int length)
throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
writeByteArrayNoTag(value, offset, length);
}
@Override
public void writeByteBuffer(final int fieldNumber, final ByteBuffer value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
writeUInt32NoTag(value.capacity());
writeRawBytes(value);
}
@Override
public void writeBytesNoTag(final ByteString value) throws IOException {
writeUInt32NoTag(value.size());
value.writeTo(this);
}
@Override
public void writeByteArrayNoTag(final byte[] value, int offset, int length) throws IOException {
writeUInt32NoTag(length);
write(value, offset, length);
}
@Override
public void writeRawBytes(final ByteBuffer value) throws IOException {
if (value.hasArray()) {
write(value.array(), value.arrayOffset(), value.capacity());
} else {
ByteBuffer duplicated = value.duplicate();
duplicated.clear();
write(duplicated);
}
}
@Override
public void writeMessage(final int fieldNumber, final MessageLite value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
writeMessageNoTag(value);
}
@Override
void writeMessage(final int fieldNumber, final MessageLite value, Schema schema)
throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
writeMessageNoTag(value, schema);
}
@Override
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);
}
@Override
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);
}
@Override
public void writeMessageNoTag(final MessageLite value) throws IOException {
writeUInt32NoTag(value.getSerializedSize());
value.writeTo(this);
}
@Override
void writeMessageNoTag(final MessageLite value, Schema schema) throws IOException {
writeUInt32NoTag(((AbstractMessageLite) value).getSerializedSize(schema));
schema.writeTo(value, wrapper);
}
@Override
public void write(byte value) throws IOException {
if (position == limit) {
doFlush();
}
buffer(value);
}
@Override
public void writeInt32NoTag(int value) throws IOException {
if (value >= 0) {
writeUInt32NoTag(value);
} else {
writeUInt64NoTag(value);
}
}
@Override
public void writeUInt32NoTag(int value) throws IOException {
flushIfNotAvailable(MAX_VARINT32_SIZE);
bufferUInt32NoTag(value);
}
@Override
public void writeFixed32NoTag(final int value) throws IOException {
flushIfNotAvailable(FIXED32_SIZE);
bufferFixed32NoTag(value);
}
@Override
public void writeUInt64NoTag(long value) throws IOException {
flushIfNotAvailable(MAX_VARINT_SIZE);
bufferUInt64NoTag(value);
}
@Override
public void writeFixed64NoTag(final long value) throws IOException {
flushIfNotAvailable(FIXED64_SIZE);
bufferFixed64NoTag(value);
}
@Override
public void writeStringNoTag(String value) throws IOException {
try {
final int maxLength = value.length() * Utf8.MAX_BYTES_PER_CHAR;
final int maxLengthVarIntSize = computeUInt32SizeNoTag(maxLength);
if (maxLengthVarIntSize + maxLength > limit) {
final byte[] encodedBytes = new byte[maxLength];
int actualLength = Utf8.encode(value, encodedBytes, 0, maxLength);
writeUInt32NoTag(actualLength);
writeLazy(encodedBytes, 0, actualLength);
return;
}
if (maxLengthVarIntSize + maxLength > limit - position) {
doFlush();
}
final int minLengthVarIntSize = computeUInt32SizeNoTag(value.length());
int oldPosition = position;
final int length;
try {
if (minLengthVarIntSize == maxLengthVarIntSize) {
position = oldPosition + minLengthVarIntSize;
int newPosition = Utf8.encode(value, buffer, position, limit - position);
position = oldPosition;
length = newPosition - oldPosition - minLengthVarIntSize;
bufferUInt32NoTag(length);
position = newPosition;
} else {
length = Utf8.encodedLength(value);
bufferUInt32NoTag(length);
position = Utf8.encode(value, buffer, position, length);
}
totalBytesWritten += length;
} catch (UnpairedSurrogateException e) {
totalBytesWritten -= position - oldPosition;
position = oldPosition;
throw e;
} catch (ArrayIndexOutOfBoundsException e) {
throw new OutOfSpaceException(e);
}
} catch (UnpairedSurrogateException e) {
inefficientWriteStringNoTag(value, e);
}
}
@Override
public void flush() throws IOException {
if (position > 0) {
doFlush();
}
}
@Override
public void write(byte[] value, int offset, int length) throws IOException {
if (limit - position >= length) {
System.arraycopy(value, offset, buffer, position, length);
position += length;
totalBytesWritten += length;
} else {
final int bytesWritten = limit - position;
System.arraycopy(value, offset, buffer, position, bytesWritten);
offset += bytesWritten;
length -= bytesWritten;
position = limit;
totalBytesWritten += bytesWritten;
doFlush();
if (length <= limit) {
System.arraycopy(value, offset, buffer, 0, length);
position = length;
} else {
out.write(value, offset, length);
}
totalBytesWritten += length;
}
}
@Override
public void writeLazy(byte[] value, int offset, int length) throws IOException {
write(value, offset, length);
}
@Override
public void write(ByteBuffer value) throws IOException {
int length = value.remaining();
if (limit - position >= length) {
value.get(buffer, position, length);
position += length;
totalBytesWritten += length;
} else {
final int bytesWritten = limit - position;
value.get(buffer, position, bytesWritten);
length -= bytesWritten;
position = limit;
totalBytesWritten += bytesWritten;
doFlush();
while (length > limit) {
value.get(buffer, 0, limit);
out.write(buffer, 0, limit);
length -= limit;
totalBytesWritten += limit;
}
value.get(buffer, 0, length);
position = length;
totalBytesWritten += length;
}
}
@Override
public void writeLazy(ByteBuffer value) throws IOException {
write(value);
}
private void flushIfNotAvailable(int requiredSize) throws IOException {
if (limit - position < requiredSize) {
doFlush();
}
}
private void doFlush() throws IOException {
out.write(buffer, 0, position);
position = 0;
}
}
}