package org.chromium.mojo.bindings;
+import org.chromium.mojo.bindings.Interface.Proxy;
import org.chromium.mojo.bindings.Struct.DataHeader;
import org.chromium.mojo.system.DataPipe;
import org.chromium.mojo.system.Handle;
import org.chromium.mojo.system.InvalidHandle;
import org.chromium.mojo.system.MessagePipeHandle;
import org.chromium.mojo.system.SharedBufferHandle;
+import org.chromium.mojo.system.UntypedHandle;
import java.nio.ByteOrder;
import java.nio.charset.Charset;
private final long mMaxMemory;
/**
+ * The number of handles in the message.
+ */
+ private final long mNumberOfHandles;
+
+ /**
* Constructor.
*/
- Validator(long maxMemory) {
+ Validator(long maxMemory, int numberOfHandles) {
mMaxMemory = maxMemory;
+ mNumberOfHandles = numberOfHandles;
}
public void claimHandle(int handle) {
throw new DeserializationException(
"Trying to access handle out of order.");
}
+ if (handle >= mNumberOfHandles) {
+ throw new DeserializationException("Trying to access non present handle.");
+ }
mMinNextClaimedHandle = handle + 1;
}
public void claimMemory(long start, long end) {
+ if (start % BindingsHelper.ALIGNMENT != 0) {
+ throw new DeserializationException("Incorrect starting alignment: " + start + ".");
+ }
if (start < mMinNextMemory) {
throw new DeserializationException("Trying to access memory out of order.");
}
if (end > mMaxMemory) {
throw new DeserializationException("Trying to access out of range memory.");
}
- if (start % BindingsHelper.ALIGNMENT != 0 || end % BindingsHelper.ALIGNMENT != 0) {
- throw new DeserializationException("Incorrect alignment.");
- }
- mMinNextMemory = end;
+ mMinNextMemory = BindingsHelper.align(end);
}
}
* @param message The message to decode.
*/
public Decoder(Message message) {
- this(message, new Validator(message.buffer.limit()), 0);
+ this(message, new Validator(message.getData().limit(), message.getHandles().size()), 0);
}
private Decoder(Message message, Validator validator, int baseOffset) {
mMessage = message;
- mMessage.buffer.order(ByteOrder.nativeOrder());
+ mMessage.getData().order(ByteOrder.nativeOrder());
mBaseOffset = baseOffset;
mValidator = validator;
- // Claim the memory for the header.
- mValidator.claimMemory(mBaseOffset, mBaseOffset + DataHeader.HEADER_SIZE);
}
/**
* Deserializes a {@link DataHeader} at the given offset.
*/
public DataHeader readDataHeader() {
+ // Claim the memory for the header.
+ mValidator.claimMemory(mBaseOffset, mBaseOffset + DataHeader.HEADER_SIZE);
int size = readInt(DataHeader.SIZE_OFFSET);
int numFields = readInt(DataHeader.NUM_FIELDS_OFFSET);
- // The memory for the header has already been claimed.
+ if (size < 0) {
+ throw new DeserializationException(
+ "Negative size. Unsigned integers are not valid for java.");
+ }
+ if (numFields < 0) {
+ throw new DeserializationException(
+ "Negative number of fields. Unsigned integers are not valid for java.");
+ }
+
+ // Claim the remaining memory.
mValidator.claimMemory(mBaseOffset + DataHeader.HEADER_SIZE, mBaseOffset + size);
DataHeader res = new DataHeader(size, numFields);
return res;
}
/**
+ * Deserializes a {@link DataHeader} at the given offset and checks if it is correct for an
+ * array where element have the given size.
+ */
+ public DataHeader readDataHeaderForPointerArray(int expectedLength) {
+ return readDataHeaderForArray(8, expectedLength);
+ }
+
+ /**
* Deserializes a byte at the given offset.
*/
public byte readByte(int offset) {
- return mMessage.buffer.get(mBaseOffset + offset);
+ validateBufferSize(offset, 1);
+ return mMessage.getData().get(mBaseOffset + offset);
}
/**
* Deserializes a boolean at the given offset, re-using any partially read byte.
*/
public boolean readBoolean(int offset, int bit) {
+ validateBufferSize(offset, 1);
return (readByte(offset) & (1 << bit)) != 0;
}
* Deserializes a short at the given offset.
*/
public short readShort(int offset) {
- return mMessage.buffer.getShort(mBaseOffset + offset);
+ validateBufferSize(offset, 2);
+ return mMessage.getData().getShort(mBaseOffset + offset);
}
/**
* Deserializes an int at the given offset.
*/
public int readInt(int offset) {
- return mMessage.buffer.getInt(mBaseOffset + offset);
+ validateBufferSize(offset, 4);
+ return mMessage.getData().getInt(mBaseOffset + offset);
}
/**
* Deserializes a float at the given offset.
*/
public float readFloat(int offset) {
- return mMessage.buffer.getFloat(mBaseOffset + offset);
+ validateBufferSize(offset, 4);
+ return mMessage.getData().getFloat(mBaseOffset + offset);
}
/**
* Deserializes a long at the given offset.
*/
public long readLong(int offset) {
- return mMessage.buffer.getLong(mBaseOffset + offset);
+ validateBufferSize(offset, 8);
+ return mMessage.getData().getLong(mBaseOffset + offset);
}
/**
* Deserializes a double at the given offset.
*/
public double readDouble(int offset) {
- return mMessage.buffer.getDouble(mBaseOffset + offset);
+ validateBufferSize(offset, 8);
+ return mMessage.getData().getDouble(mBaseOffset + offset);
}
/**
* Deserializes a pointer at the given offset. Returns a Decoder suitable to decode the content
* of the pointer.
*/
- public Decoder readPointer(int offset) {
+ public Decoder readPointer(int offset, boolean nullable) {
int basePosition = mBaseOffset + offset;
long pointerOffset = readLong(offset);
if (pointerOffset == 0) {
+ if (!nullable) {
+ throw new DeserializationException(
+ "Trying to decode null pointer for a non-nullable type.");
+ }
return null;
}
int newPosition = (int) (basePosition + pointerOffset);
/**
* Deserializes an array of boolean at the given offset.
*/
- public boolean[] readBooleans(int offset) {
- Decoder d = readPointer(offset);
+ public boolean[] readBooleans(int offset, int arrayNullability, int expectedLength) {
+ Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
if (d == null) {
return null;
}
- DataHeader si = d.readDataHeader();
- byte[] bytes = new byte[si.numFields + 7 / BindingsHelper.ALIGNMENT];
- d.mMessage.buffer.position(d.mBaseOffset + DataHeader.HEADER_SIZE);
- d.mMessage.buffer.get(bytes);
+ DataHeader si = d.readDataHeaderForBooleanArray(expectedLength);
+ byte[] bytes = new byte[(si.numFields + 7) / BindingsHelper.ALIGNMENT];
+ d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE);
+ d.mMessage.getData().get(bytes);
boolean[] result = new boolean[si.numFields];
for (int i = 0; i < bytes.length; ++i) {
for (int j = 0; j < BindingsHelper.ALIGNMENT; ++j) {
/**
* Deserializes an array of bytes at the given offset.
*/
- public byte[] readBytes(int offset) {
- Decoder d = readPointer(offset);
+ public byte[] readBytes(int offset, int arrayNullability, int expectedLength) {
+ Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
if (d == null) {
return null;
}
- DataHeader si = d.readDataHeader();
+ DataHeader si = d.readDataHeaderForArray(1, expectedLength);
byte[] result = new byte[si.numFields];
- d.mMessage.buffer.position(d.mBaseOffset + DataHeader.HEADER_SIZE);
- d.mMessage.buffer.get(result);
+ d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE);
+ d.mMessage.getData().get(result);
return result;
}
/**
* Deserializes an array of shorts at the given offset.
*/
- public short[] readShorts(int offset) {
- Decoder d = readPointer(offset);
+ public short[] readShorts(int offset, int arrayNullability, int expectedLength) {
+ Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
if (d == null) {
return null;
}
- DataHeader si = d.readDataHeader();
+ DataHeader si = d.readDataHeaderForArray(2, expectedLength);
short[] result = new short[si.numFields];
- d.mMessage.buffer.position(d.mBaseOffset + DataHeader.HEADER_SIZE);
- d.mMessage.buffer.asShortBuffer().get(result);
+ d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE);
+ d.mMessage.getData().asShortBuffer().get(result);
return result;
}
/**
* Deserializes an array of ints at the given offset.
*/
- public int[] readInts(int offset) {
- Decoder d = readPointer(offset);
+ public int[] readInts(int offset, int arrayNullability, int expectedLength) {
+ Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
if (d == null) {
return null;
}
- DataHeader si = d.readDataHeader();
+ DataHeader si = d.readDataHeaderForArray(4, expectedLength);
int[] result = new int[si.numFields];
- d.mMessage.buffer.position(d.mBaseOffset + DataHeader.HEADER_SIZE);
- d.mMessage.buffer.asIntBuffer().get(result);
+ d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE);
+ d.mMessage.getData().asIntBuffer().get(result);
return result;
}
/**
* Deserializes an array of floats at the given offset.
*/
- public float[] readFloats(int offset) {
- Decoder d = readPointer(offset);
+ public float[] readFloats(int offset, int arrayNullability, int expectedLength) {
+ Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
if (d == null) {
return null;
}
- DataHeader si = d.readDataHeader();
+ DataHeader si = d.readDataHeaderForArray(4, expectedLength);
float[] result = new float[si.numFields];
- d.mMessage.buffer.position(d.mBaseOffset + DataHeader.HEADER_SIZE);
- d.mMessage.buffer.asFloatBuffer().get(result);
+ d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE);
+ d.mMessage.getData().asFloatBuffer().get(result);
return result;
}
/**
* Deserializes an array of longs at the given offset.
*/
- public long[] readLongs(int offset) {
- Decoder d = readPointer(offset);
+ public long[] readLongs(int offset, int arrayNullability, int expectedLength) {
+ Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
if (d == null) {
return null;
}
- DataHeader si = d.readDataHeader();
+ DataHeader si = d.readDataHeaderForArray(8, expectedLength);
long[] result = new long[si.numFields];
- d.mMessage.buffer.position(d.mBaseOffset + DataHeader.HEADER_SIZE);
- d.mMessage.buffer.asLongBuffer().get(result);
+ d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE);
+ d.mMessage.getData().asLongBuffer().get(result);
return result;
}
/**
* Deserializes an array of doubles at the given offset.
*/
- public double[] readDoubles(int offset) {
- Decoder d = readPointer(offset);
+ public double[] readDoubles(int offset, int arrayNullability, int expectedLength) {
+ Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
if (d == null) {
return null;
}
- DataHeader si = d.readDataHeader();
+ DataHeader si = d.readDataHeaderForArray(8, expectedLength);
double[] result = new double[si.numFields];
- d.mMessage.buffer.position(d.mBaseOffset + DataHeader.HEADER_SIZE);
- d.mMessage.buffer.asDoubleBuffer().get(result);
+ d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE);
+ d.mMessage.getData().asDoubleBuffer().get(result);
return result;
}
/**
* Deserializes an |Handle| at the given offset.
*/
- public Handle readHandle(int offset) {
+ public Handle readHandle(int offset, boolean nullable) {
int index = readInt(offset);
if (index == -1) {
+ if (!nullable) {
+ throw new DeserializationException(
+ "Trying to decode an invalid handle for a non-nullable type.");
+ }
return InvalidHandle.INSTANCE;
}
mValidator.claimHandle(index);
- return mMessage.handles.get(index);
+ return mMessage.getHandles().get(index);
+ }
+
+ /**
+ * Deserializes an |UntypedHandle| at the given offset.
+ */
+ public UntypedHandle readUntypedHandle(int offset, boolean nullable) {
+ return readHandle(offset, nullable).toUntypedHandle();
}
/**
* Deserializes a |ConsumerHandle| at the given offset.
*/
- public DataPipe.ConsumerHandle readConsumerHandle(int offset) {
- return readHandle(offset).toUntypedHandle().toDataPipeConsumerHandle();
+ public DataPipe.ConsumerHandle readConsumerHandle(int offset, boolean nullable) {
+ return readUntypedHandle(offset, nullable).toDataPipeConsumerHandle();
}
/**
* Deserializes a |ProducerHandle| at the given offset.
*/
- public DataPipe.ProducerHandle readProducerHandle(int offset) {
- return readHandle(offset).toUntypedHandle().toDataPipeProducerHandle();
+ public DataPipe.ProducerHandle readProducerHandle(int offset, boolean nullable) {
+ return readUntypedHandle(offset, nullable).toDataPipeProducerHandle();
}
/**
* Deserializes a |MessagePipeHandle| at the given offset.
*/
- public MessagePipeHandle readMessagePipeHandle(int offset) {
- return readHandle(offset).toUntypedHandle().toMessagePipeHandle();
+ public MessagePipeHandle readMessagePipeHandle(int offset, boolean nullable) {
+ return readUntypedHandle(offset, nullable).toMessagePipeHandle();
}
/**
* Deserializes a |SharedBufferHandle| at the given offset.
*/
- public SharedBufferHandle readSharedBufferHandle(int offset) {
- return readHandle(offset).toUntypedHandle().toSharedBufferHandle();
+ public SharedBufferHandle readSharedBufferHandle(int offset, boolean nullable) {
+ return readUntypedHandle(offset, nullable).toSharedBufferHandle();
}
/**
- * Deserializes a |ServiceHandle| at the given offset.
+ * Deserializes an interface at the given offset.
+ *
+ * @return a proxy to the service.
*/
- public <S extends Interface> S readServiceInterface(int offset, Object builder) {
- // TODO(qsr): To be implemented when interfaces proxy and stubs are implemented.
- throw new UnsupportedOperationException("Unimplemented operation");
+ public <P extends Proxy> P readServiceInterface(int offset, boolean nullable,
+ Interface.Manager<?, P> manager) {
+ MessagePipeHandle handle = readMessagePipeHandle(offset, nullable);
+ if (!handle.isValid()) {
+ return null;
+ }
+ return manager.attachProxy(handle);
}
/**
* Deserializes a |InterfaceRequest| at the given offset.
*/
- public <S extends Interface> InterfaceRequest<S> readInterfaceRequest(int offset) {
- // TODO(qsr): To be implemented when interfaces proxy and stubs are implemented.
- throw new UnsupportedOperationException("Unimplemented operation");
+ public <I extends Interface> InterfaceRequest<I> readInterfaceRequest(int offset,
+ boolean nullable) {
+ MessagePipeHandle handle = readMessagePipeHandle(offset, nullable);
+ if (handle == null) {
+ return null;
+ }
+ return new InterfaceRequest<I>(handle);
}
/**
* Deserializes a string at the given offset.
*/
- public String readString(int offset) {
- byte[] bytes = readBytes(offset);
+ public String readString(int offset, boolean nullable) {
+ final int arrayNullability = nullable ? BindingsHelper.ARRAY_NULLABLE : 0;
+ byte[] bytes = readBytes(offset, arrayNullability, BindingsHelper.UNSPECIFIED_ARRAY_LENGTH);
if (bytes == null) {
return null;
}
/**
* Deserializes an array of |Handle| at the given offset.
*/
- public Handle[] readHandles(int offset) {
- Decoder d = readPointer(offset);
+ public Handle[] readHandles(int offset, int arrayNullability, int expectedLength) {
+ Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
if (d == null) {
return null;
}
- DataHeader si = d.readDataHeader();
+ DataHeader si = d.readDataHeaderForArray(4, expectedLength);
Handle[] result = new Handle[si.numFields];
for (int i = 0; i < result.length; ++i) {
result[i] = d.readHandle(
- DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i);
+ DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i,
+ BindingsHelper.isElementNullable(arrayNullability));
+ }
+ return result;
+ }
+
+ /**
+ * Deserializes an array of |UntypedHandle| at the given offset.
+ */
+ public UntypedHandle[] readUntypedHandles(
+ int offset, int arrayNullability, int expectedLength) {
+ Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
+ if (d == null) {
+ return null;
+ }
+ DataHeader si = d.readDataHeaderForArray(4, expectedLength);
+ UntypedHandle[] result = new UntypedHandle[si.numFields];
+ for (int i = 0; i < result.length; ++i) {
+ result[i] = d.readUntypedHandle(
+ DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i,
+ BindingsHelper.isElementNullable(arrayNullability));
}
return result;
}
/**
* Deserializes an array of |ConsumerHandle| at the given offset.
*/
- public DataPipe.ConsumerHandle[] readConsumerHandles(int offset) {
- Decoder d = readPointer(offset);
+ public DataPipe.ConsumerHandle[] readConsumerHandles(
+ int offset, int arrayNullability, int expectedLength) {
+ Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
if (d == null) {
return null;
}
- DataHeader si = d.readDataHeader();
+ DataHeader si = d.readDataHeaderForArray(4, expectedLength);
DataPipe.ConsumerHandle[] result = new DataPipe.ConsumerHandle[si.numFields];
for (int i = 0; i < result.length; ++i) {
result[i] = d.readConsumerHandle(
- DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i);
+ DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i,
+ BindingsHelper.isElementNullable(arrayNullability));
}
return result;
}
/**
* Deserializes an array of |ProducerHandle| at the given offset.
*/
- public DataPipe.ProducerHandle[] readProducerHandles(int offset) {
- Decoder d = readPointer(offset);
+ public DataPipe.ProducerHandle[] readProducerHandles(
+ int offset, int arrayNullability, int expectedLength) {
+ Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
if (d == null) {
return null;
}
- DataHeader si = d.readDataHeader();
+ DataHeader si = d.readDataHeaderForArray(4, expectedLength);
DataPipe.ProducerHandle[] result = new DataPipe.ProducerHandle[si.numFields];
for (int i = 0; i < result.length; ++i) {
result[i] = d.readProducerHandle(
- DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i);
+ DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i,
+ BindingsHelper.isElementNullable(arrayNullability));
}
return result;
/**
* Deserializes an array of |MessagePipeHandle| at the given offset.
*/
- public MessagePipeHandle[] readMessagePipeHandles(int offset) {
- Decoder d = readPointer(offset);
+ public MessagePipeHandle[] readMessagePipeHandles(
+ int offset, int arrayNullability, int expectedLength) {
+ Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
if (d == null) {
return null;
}
- DataHeader si = d.readDataHeader();
+ DataHeader si = d.readDataHeaderForArray(4, expectedLength);
MessagePipeHandle[] result = new MessagePipeHandle[si.numFields];
for (int i = 0; i < result.length; ++i) {
result[i] = d.readMessagePipeHandle(
- DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i);
+ DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i,
+ BindingsHelper.isElementNullable(arrayNullability));
}
return result;
/**
* Deserializes an array of |SharedBufferHandle| at the given offset.
*/
- public SharedBufferHandle[] readSharedBufferHandles(int offset) {
- Decoder d = readPointer(offset);
+ public SharedBufferHandle[] readSharedBufferHandles(
+ int offset, int arrayNullability, int expectedLength) {
+ Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
if (d == null) {
return null;
}
- DataHeader si = d.readDataHeader();
+ DataHeader si = d.readDataHeaderForArray(4, expectedLength);
SharedBufferHandle[] result = new SharedBufferHandle[si.numFields];
for (int i = 0; i < result.length; ++i) {
result[i] = d.readSharedBufferHandle(
- DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i);
+ DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i,
+ BindingsHelper.isElementNullable(arrayNullability));
}
return result;
/**
* Deserializes an array of |ServiceHandle| at the given offset.
*/
- public <S extends Interface> S[] readServiceInterfaces(int offset, Object builder) {
- // TODO(qsr): To be implemented when interfaces proxy and stubs are implemented.
- throw new UnsupportedOperationException("Unimplemented operation");
+ public <S extends Interface, P extends Proxy> S[] readServiceInterfaces(
+ int offset, int arrayNullability, int expectedLength, Interface.Manager<S, P> manager) {
+ Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
+ if (d == null) {
+ return null;
+ }
+ DataHeader si = d.readDataHeaderForArray(4, expectedLength);
+ S[] result = manager.buildArray(si.numFields);
+ for (int i = 0; i < result.length; ++i) {
+ // This cast is necessary because java 6 doesn't handle wildcard correctly when using
+ // Manager<S, ? extends S>
+ @SuppressWarnings("unchecked")
+ S value = (S) d.readServiceInterface(
+ DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i,
+ BindingsHelper.isElementNullable(arrayNullability), manager);
+ result[i] = value;
+ }
+ return result;
}
/**
* Deserializes an array of |InterfaceRequest| at the given offset.
*/
- public <S extends Interface> InterfaceRequest<S>[] readInterfaceRequests(int offset) {
- Decoder d = readPointer(offset);
+ public <I extends Interface> InterfaceRequest<I>[] readInterfaceRequests(
+ int offset, int arrayNullability, int expectedLength) {
+ Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
if (d == null) {
return null;
}
- DataHeader si = d.readDataHeader();
+ DataHeader si = d.readDataHeaderForArray(4, expectedLength);
@SuppressWarnings("unchecked")
- InterfaceRequest<S>[] result = new InterfaceRequest[si.numFields];
+ InterfaceRequest<I>[] result = new InterfaceRequest[si.numFields];
for (int i = 0; i < result.length; ++i) {
result[i] = d.readInterfaceRequest(
- DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i);
+ DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i,
+ BindingsHelper.isElementNullable(arrayNullability));
}
return result;
}
return new Decoder(mMessage, mValidator, offset);
}
+ /**
+ * Deserializes a {@link DataHeader} at the given offset and checks if it is correct for an
+ * array of booleans.
+ */
+ private DataHeader readDataHeaderForBooleanArray(int expectedLength) {
+ DataHeader dataHeader = readDataHeader();
+ if (dataHeader.size < DataHeader.HEADER_SIZE + (dataHeader.numFields + 7) / 8) {
+ throw new DeserializationException("Array header is incorrect.");
+ }
+ if (expectedLength != BindingsHelper.UNSPECIFIED_ARRAY_LENGTH
+ && dataHeader.numFields != expectedLength) {
+ throw new DeserializationException("Incorrect array length. Expected: " +
+ expectedLength + ", but got: " + dataHeader.numFields + ".");
+ }
+ return dataHeader;
+ }
+
+ /**
+ * Deserializes a {@link DataHeader} of an array at the given offset.
+ */
+ private DataHeader readDataHeaderForArray(long elementSize, int expectedLength) {
+ DataHeader dataHeader = readDataHeader();
+ if (dataHeader.size < (DataHeader.HEADER_SIZE + elementSize * dataHeader.numFields)) {
+ throw new DeserializationException("Array header is incorrect.");
+ }
+ if (expectedLength != BindingsHelper.UNSPECIFIED_ARRAY_LENGTH
+ && dataHeader.numFields != expectedLength) {
+ throw new DeserializationException("Incorrect array length. Expected: " +
+ expectedLength + ", but got: " + dataHeader.numFields + ".");
+ }
+ return dataHeader;
+ }
+
+ private void validateBufferSize(int offset, int size) {
+ if (mMessage.getData().limit() < offset + size) {
+ throw new DeserializationException("Buffer is smaller than expected.");
+ }
+ }
}