1116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Copyright 2014 The Chromium Authors. All rights reserved. 2116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 3116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// found in the LICENSE file. 4116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 5116680a4aac90f2aa7413d9095a592090648e557Ben Murdochpackage org.chromium.mojo.bindings; 6116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport org.chromium.mojo.bindings.Interface.Proxy; 8116680a4aac90f2aa7413d9095a592090648e557Ben Murdochimport org.chromium.mojo.bindings.Struct.DataHeader; 9116680a4aac90f2aa7413d9095a592090648e557Ben Murdochimport org.chromium.mojo.system.DataPipe; 10116680a4aac90f2aa7413d9095a592090648e557Ben Murdochimport org.chromium.mojo.system.Handle; 11116680a4aac90f2aa7413d9095a592090648e557Ben Murdochimport org.chromium.mojo.system.InvalidHandle; 12116680a4aac90f2aa7413d9095a592090648e557Ben Murdochimport org.chromium.mojo.system.MessagePipeHandle; 13116680a4aac90f2aa7413d9095a592090648e557Ben Murdochimport org.chromium.mojo.system.SharedBufferHandle; 1403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)import org.chromium.mojo.system.UntypedHandle; 15116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 16116680a4aac90f2aa7413d9095a592090648e557Ben Murdochimport java.nio.ByteOrder; 17116680a4aac90f2aa7413d9095a592090648e557Ben Murdochimport java.nio.charset.Charset; 18116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 19116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch/** 20116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * A Decoder is a helper class for deserializing a mojo struct. It enables deserialization of basic 21116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * types from a {@link Message} object at a given offset into it's byte buffer. 22116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 23116680a4aac90f2aa7413d9095a592090648e557Ben Murdochpublic class Decoder { 24116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 25116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 26116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Helper class to validate the decoded message. 27116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 28116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch static final class Validator { 29116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 30116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 31116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Minimal value for the next handle to deserialize. 32116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 33116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch private int mMinNextClaimedHandle = 0; 34116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 35116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Minimal value of the start of the next memory to claim. 36116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 37116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch private long mMinNextMemory = 0; 38116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 39116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 40116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * The maximal memory accessible. 41116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 42116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch private final long mMaxMemory; 43116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 44116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * The number of handles in the message. 461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci */ 471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private final long mNumberOfHandles; 481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci /** 50116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Constructor. 51116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Validator(long maxMemory, int numberOfHandles) { 53116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch mMaxMemory = maxMemory; 541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci mNumberOfHandles = numberOfHandles; 55116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 56116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 57116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch public void claimHandle(int handle) { 58116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (handle < mMinNextClaimedHandle) { 59116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch throw new DeserializationException( 60116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch "Trying to access handle out of order."); 61116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (handle >= mNumberOfHandles) { 631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci throw new DeserializationException("Trying to access non present handle."); 641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 65116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch mMinNextClaimedHandle = handle + 1; 66116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 67116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 68116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch public void claimMemory(long start, long end) { 691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (start % BindingsHelper.ALIGNMENT != 0) { 701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci throw new DeserializationException("Incorrect starting alignment: " + start + "."); 711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 72116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (start < mMinNextMemory) { 73116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch throw new DeserializationException("Trying to access memory out of order."); 74116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 75116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (end < start) { 76116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch throw new DeserializationException("Incorrect memory range."); 77116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 78116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (end > mMaxMemory) { 79116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch throw new DeserializationException("Trying to access out of range memory."); 80116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci mMinNextMemory = BindingsHelper.align(end); 82116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 83116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 84116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 85116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 86116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * The message to deserialize from. 87116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 88116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch private final Message mMessage; 89116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 90116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 91116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * The base offset in the byte buffer. 92116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 93116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch private final int mBaseOffset; 94116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 95116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 96116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Validator for the decoded message. 97116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 98116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch private final Validator mValidator; 99116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 100116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 101116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Constructor. 102116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * 103116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * @param message The message to decode. 104116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 105116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch public Decoder(Message message) { 1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci this(message, new Validator(message.getData().limit(), message.getHandles().size()), 0); 107116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 108116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 109116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch private Decoder(Message message, Validator validator, int baseOffset) { 110116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch mMessage = message; 1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci mMessage.getData().order(ByteOrder.nativeOrder()); 112116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch mBaseOffset = baseOffset; 113116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch mValidator = validator; 114116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 115116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 116116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 117116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Deserializes a {@link DataHeader} at the given offset. 118116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 119116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch public DataHeader readDataHeader() { 1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Claim the memory for the header. 1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci mValidator.claimMemory(mBaseOffset, mBaseOffset + DataHeader.HEADER_SIZE); 122116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int size = readInt(DataHeader.SIZE_OFFSET); 123116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int numFields = readInt(DataHeader.NUM_FIELDS_OFFSET); 1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (size < 0) { 1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci throw new DeserializationException( 1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "Negative size. Unsigned integers are not valid for java."); 1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (numFields < 0) { 1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci throw new DeserializationException( 1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "Negative number of fields. Unsigned integers are not valid for java."); 1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Claim the remaining memory. 134116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch mValidator.claimMemory(mBaseOffset + DataHeader.HEADER_SIZE, mBaseOffset + size); 135116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DataHeader res = new DataHeader(size, numFields); 136116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return res; 137116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 138116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 139116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * Deserializes a {@link DataHeader} at the given offset and checks if it is correct for an 1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * array where element have the given size. 1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci */ 1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public DataHeader readDataHeaderForPointerArray(int expectedLength) { 1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return readDataHeaderForArray(8, expectedLength); 1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci /** 148116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Deserializes a byte at the given offset. 149116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 150116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch public byte readByte(int offset) { 1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci validateBufferSize(offset, 1); 1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return mMessage.getData().get(mBaseOffset + offset); 153116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 154116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 155116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 156116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Deserializes a boolean at the given offset, re-using any partially read byte. 157116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 158116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch public boolean readBoolean(int offset, int bit) { 1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci validateBufferSize(offset, 1); 160116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return (readByte(offset) & (1 << bit)) != 0; 161116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 162116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 163116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 164116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Deserializes a short at the given offset. 165116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 166116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch public short readShort(int offset) { 1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci validateBufferSize(offset, 2); 1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return mMessage.getData().getShort(mBaseOffset + offset); 169116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 170116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 171116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 172116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Deserializes an int at the given offset. 173116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 174116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch public int readInt(int offset) { 1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci validateBufferSize(offset, 4); 1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return mMessage.getData().getInt(mBaseOffset + offset); 177116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 178116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 179116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 180116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Deserializes a float at the given offset. 181116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 182116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch public float readFloat(int offset) { 1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci validateBufferSize(offset, 4); 1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return mMessage.getData().getFloat(mBaseOffset + offset); 185116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 186116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 187116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 188116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Deserializes a long at the given offset. 189116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 190116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch public long readLong(int offset) { 1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci validateBufferSize(offset, 8); 1921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return mMessage.getData().getLong(mBaseOffset + offset); 193116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 194116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 195116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 196116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Deserializes a double at the given offset. 197116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 198116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch public double readDouble(int offset) { 1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci validateBufferSize(offset, 8); 2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return mMessage.getData().getDouble(mBaseOffset + offset); 201116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 202116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 203116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 204116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Deserializes a pointer at the given offset. Returns a Decoder suitable to decode the content 205116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * of the pointer. 206116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 2071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public Decoder readPointer(int offset, boolean nullable) { 208116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int basePosition = mBaseOffset + offset; 209116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch long pointerOffset = readLong(offset); 210116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (pointerOffset == 0) { 2111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!nullable) { 2121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci throw new DeserializationException( 2131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "Trying to decode null pointer for a non-nullable type."); 2141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 215116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return null; 216116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 217116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int newPosition = (int) (basePosition + pointerOffset); 218116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // The method |getDecoderAtPosition| will validate that the pointer address is valid. 219116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return getDecoderAtPosition(newPosition); 220116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 221116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 222116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 223116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 224116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Deserializes an array of boolean at the given offset. 225116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 2261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public boolean[] readBooleans(int offset, int arrayNullability, int expectedLength) { 2271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability)); 228116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (d == null) { 229116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return null; 230116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 2311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DataHeader si = d.readDataHeaderForBooleanArray(expectedLength); 2321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci byte[] bytes = new byte[(si.numFields + 7) / BindingsHelper.ALIGNMENT]; 2331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE); 2341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci d.mMessage.getData().get(bytes); 235116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch boolean[] result = new boolean[si.numFields]; 236116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (int i = 0; i < bytes.length; ++i) { 237116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (int j = 0; j < BindingsHelper.ALIGNMENT; ++j) { 238116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int booleanIndex = i * BindingsHelper.ALIGNMENT + j; 239116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (booleanIndex < result.length) { 240116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch result[booleanIndex] = (bytes[i] & (1 << j)) != 0; 241116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 242116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 243116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 244116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return result; 245116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 246116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 247116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 248116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Deserializes an array of bytes at the given offset. 249116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 2501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public byte[] readBytes(int offset, int arrayNullability, int expectedLength) { 2511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability)); 252116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (d == null) { 253116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return null; 254116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 2551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DataHeader si = d.readDataHeaderForArray(1, expectedLength); 256116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch byte[] result = new byte[si.numFields]; 2571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE); 2581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci d.mMessage.getData().get(result); 259116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return result; 260116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 261116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 262116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 263116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Deserializes an array of shorts at the given offset. 264116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 2651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public short[] readShorts(int offset, int arrayNullability, int expectedLength) { 2661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability)); 267116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (d == null) { 268116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return null; 269116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 2701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DataHeader si = d.readDataHeaderForArray(2, expectedLength); 271116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch short[] result = new short[si.numFields]; 2721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE); 2731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci d.mMessage.getData().asShortBuffer().get(result); 274116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return result; 275116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 276116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 277116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 278116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Deserializes an array of ints at the given offset. 279116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 2801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public int[] readInts(int offset, int arrayNullability, int expectedLength) { 2811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability)); 282116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (d == null) { 283116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return null; 284116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 2851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DataHeader si = d.readDataHeaderForArray(4, expectedLength); 286116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int[] result = new int[si.numFields]; 2871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE); 2881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci d.mMessage.getData().asIntBuffer().get(result); 289116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return result; 290116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 291116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 292116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 293116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Deserializes an array of floats at the given offset. 294116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 2951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public float[] readFloats(int offset, int arrayNullability, int expectedLength) { 2961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability)); 297116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (d == null) { 298116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return null; 299116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 3001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DataHeader si = d.readDataHeaderForArray(4, expectedLength); 301116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch float[] result = new float[si.numFields]; 3021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE); 3031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci d.mMessage.getData().asFloatBuffer().get(result); 304116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return result; 305116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 306116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 307116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 308116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Deserializes an array of longs at the given offset. 309116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 3101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public long[] readLongs(int offset, int arrayNullability, int expectedLength) { 3111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability)); 312116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (d == null) { 313116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return null; 314116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 3151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DataHeader si = d.readDataHeaderForArray(8, expectedLength); 316116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch long[] result = new long[si.numFields]; 3171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE); 3181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci d.mMessage.getData().asLongBuffer().get(result); 319116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return result; 320116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 321116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 322116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 323116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Deserializes an array of doubles at the given offset. 324116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 3251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public double[] readDoubles(int offset, int arrayNullability, int expectedLength) { 3261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability)); 327116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (d == null) { 328116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return null; 329116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 3301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DataHeader si = d.readDataHeaderForArray(8, expectedLength); 331116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch double[] result = new double[si.numFields]; 3321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE); 3331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci d.mMessage.getData().asDoubleBuffer().get(result); 334116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return result; 335116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 336116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 337116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 338116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Deserializes an |Handle| at the given offset. 339116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 3401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public Handle readHandle(int offset, boolean nullable) { 341116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int index = readInt(offset); 342116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (index == -1) { 3431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!nullable) { 3441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci throw new DeserializationException( 3451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "Trying to decode an invalid handle for a non-nullable type."); 3461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 347116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return InvalidHandle.INSTANCE; 348116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 349116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch mValidator.claimHandle(index); 3501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return mMessage.getHandles().get(index); 351116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 352116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 353116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 35403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) * Deserializes an |UntypedHandle| at the given offset. 35503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) */ 3561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public UntypedHandle readUntypedHandle(int offset, boolean nullable) { 3571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return readHandle(offset, nullable).toUntypedHandle(); 35803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 35903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 36003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) /** 361116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Deserializes a |ConsumerHandle| at the given offset. 362116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 3631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public DataPipe.ConsumerHandle readConsumerHandle(int offset, boolean nullable) { 3641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return readUntypedHandle(offset, nullable).toDataPipeConsumerHandle(); 365116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 366116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 367116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 368116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Deserializes a |ProducerHandle| at the given offset. 369116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 3701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public DataPipe.ProducerHandle readProducerHandle(int offset, boolean nullable) { 3711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return readUntypedHandle(offset, nullable).toDataPipeProducerHandle(); 372116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 373116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 374116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 375116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Deserializes a |MessagePipeHandle| at the given offset. 376116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 3771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public MessagePipeHandle readMessagePipeHandle(int offset, boolean nullable) { 3781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return readUntypedHandle(offset, nullable).toMessagePipeHandle(); 379116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 380116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 381116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 382116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Deserializes a |SharedBufferHandle| at the given offset. 383116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 3841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public SharedBufferHandle readSharedBufferHandle(int offset, boolean nullable) { 3851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return readUntypedHandle(offset, nullable).toSharedBufferHandle(); 386116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 387116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 388116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 3891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * Deserializes an interface at the given offset. 3901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * 3911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @return a proxy to the service. 392116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 3931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public <P extends Proxy> P readServiceInterface(int offset, boolean nullable, 3941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Interface.Manager<?, P> manager) { 3951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MessagePipeHandle handle = readMessagePipeHandle(offset, nullable); 3961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!handle.isValid()) { 3971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return null; 3981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 3991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return manager.attachProxy(handle); 400116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 401116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 402116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 403116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Deserializes a |InterfaceRequest| at the given offset. 404116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 4051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public <I extends Interface> InterfaceRequest<I> readInterfaceRequest(int offset, 4061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci boolean nullable) { 4071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci MessagePipeHandle handle = readMessagePipeHandle(offset, nullable); 4081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (handle == null) { 4091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return null; 4101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 4111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return new InterfaceRequest<I>(handle); 412116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 413116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 414116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 415116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Deserializes a string at the given offset. 416116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 4171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public String readString(int offset, boolean nullable) { 4181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci final int arrayNullability = nullable ? BindingsHelper.ARRAY_NULLABLE : 0; 4191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci byte[] bytes = readBytes(offset, arrayNullability, BindingsHelper.UNSPECIFIED_ARRAY_LENGTH); 420116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (bytes == null) { 421116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return null; 422116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 423116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return new String(bytes, Charset.forName("utf8")); 424116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 425116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 426116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 427116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Deserializes an array of |Handle| at the given offset. 428116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 4291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public Handle[] readHandles(int offset, int arrayNullability, int expectedLength) { 4301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability)); 431116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (d == null) { 432116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return null; 433116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 4341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DataHeader si = d.readDataHeaderForArray(4, expectedLength); 435116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch Handle[] result = new Handle[si.numFields]; 436116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (int i = 0; i < result.length; ++i) { 437116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch result[i] = d.readHandle( 4381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i, 4391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BindingsHelper.isElementNullable(arrayNullability)); 4401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 4411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return result; 4421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 4431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci /** 4451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * Deserializes an array of |UntypedHandle| at the given offset. 4461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci */ 4471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public UntypedHandle[] readUntypedHandles( 4481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int offset, int arrayNullability, int expectedLength) { 4491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability)); 4501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (d == null) { 4511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return null; 4521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 4531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DataHeader si = d.readDataHeaderForArray(4, expectedLength); 4541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci UntypedHandle[] result = new UntypedHandle[si.numFields]; 4551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (int i = 0; i < result.length; ++i) { 4561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci result[i] = d.readUntypedHandle( 4571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i, 4581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BindingsHelper.isElementNullable(arrayNullability)); 459116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 460116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return result; 461116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 462116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 463116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 464116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Deserializes an array of |ConsumerHandle| at the given offset. 465116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 4661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public DataPipe.ConsumerHandle[] readConsumerHandles( 4671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int offset, int arrayNullability, int expectedLength) { 4681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability)); 469116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (d == null) { 470116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return null; 471116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 4721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DataHeader si = d.readDataHeaderForArray(4, expectedLength); 473116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DataPipe.ConsumerHandle[] result = new DataPipe.ConsumerHandle[si.numFields]; 474116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (int i = 0; i < result.length; ++i) { 475116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch result[i] = d.readConsumerHandle( 4761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i, 4771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BindingsHelper.isElementNullable(arrayNullability)); 478116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 479116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return result; 480116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 481116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 482116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 483116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Deserializes an array of |ProducerHandle| at the given offset. 484116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 4851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public DataPipe.ProducerHandle[] readProducerHandles( 4861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int offset, int arrayNullability, int expectedLength) { 4871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability)); 488116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (d == null) { 489116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return null; 490116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 4911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DataHeader si = d.readDataHeaderForArray(4, expectedLength); 492116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DataPipe.ProducerHandle[] result = new DataPipe.ProducerHandle[si.numFields]; 493116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (int i = 0; i < result.length; ++i) { 494116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch result[i] = d.readProducerHandle( 4951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i, 4961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BindingsHelper.isElementNullable(arrayNullability)); 497116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 498116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return result; 499116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 500116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 501116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 502116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 503116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Deserializes an array of |MessagePipeHandle| at the given offset. 504116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 5051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public MessagePipeHandle[] readMessagePipeHandles( 5061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int offset, int arrayNullability, int expectedLength) { 5071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability)); 508116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (d == null) { 509116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return null; 510116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 5111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DataHeader si = d.readDataHeaderForArray(4, expectedLength); 512116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch MessagePipeHandle[] result = new MessagePipeHandle[si.numFields]; 513116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (int i = 0; i < result.length; ++i) { 514116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch result[i] = d.readMessagePipeHandle( 5151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i, 5161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BindingsHelper.isElementNullable(arrayNullability)); 517116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 518116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return result; 519116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 520116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 521116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 522116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 523116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Deserializes an array of |SharedBufferHandle| at the given offset. 524116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 5251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public SharedBufferHandle[] readSharedBufferHandles( 5261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int offset, int arrayNullability, int expectedLength) { 5271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability)); 528116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (d == null) { 529116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return null; 530116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 5311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DataHeader si = d.readDataHeaderForArray(4, expectedLength); 532116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SharedBufferHandle[] result = new SharedBufferHandle[si.numFields]; 533116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (int i = 0; i < result.length; ++i) { 534116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch result[i] = d.readSharedBufferHandle( 5351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i, 5361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BindingsHelper.isElementNullable(arrayNullability)); 537116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 538116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return result; 539116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 540116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 541116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 542116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 543116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Deserializes an array of |ServiceHandle| at the given offset. 544116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 5451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public <S extends Interface, P extends Proxy> S[] readServiceInterfaces( 5461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int offset, int arrayNullability, int expectedLength, Interface.Manager<S, P> manager) { 5471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability)); 5481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (d == null) { 5491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return null; 5501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 5511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DataHeader si = d.readDataHeaderForArray(4, expectedLength); 5521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci S[] result = manager.buildArray(si.numFields); 5531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (int i = 0; i < result.length; ++i) { 5541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // This cast is necessary because java 6 doesn't handle wildcard correctly when using 5551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Manager<S, ? extends S> 5561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci @SuppressWarnings("unchecked") 5571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci S value = (S) d.readServiceInterface( 5581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i, 5591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BindingsHelper.isElementNullable(arrayNullability), manager); 5601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci result[i] = value; 5611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 5621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return result; 563116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 564116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 565116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 566116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Deserializes an array of |InterfaceRequest| at the given offset. 567116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 5681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public <I extends Interface> InterfaceRequest<I>[] readInterfaceRequests( 5691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int offset, int arrayNullability, int expectedLength) { 5701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability)); 571116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (d == null) { 572116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return null; 573116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 5741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DataHeader si = d.readDataHeaderForArray(4, expectedLength); 575116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch @SuppressWarnings("unchecked") 5761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci InterfaceRequest<I>[] result = new InterfaceRequest[si.numFields]; 577116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (int i = 0; i < result.length; ++i) { 578116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch result[i] = d.readInterfaceRequest( 5791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i, 5801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BindingsHelper.isElementNullable(arrayNullability)); 581116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 582116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return result; 583116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 584116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 585116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 586116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Returns a view of this decoder at the offset |offset|. 587116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 588116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch private Decoder getDecoderAtPosition(int offset) { 589116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return new Decoder(mMessage, mValidator, offset); 590116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 591116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 5921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci /** 5931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * Deserializes a {@link DataHeader} at the given offset and checks if it is correct for an 5941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * array of booleans. 5951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci */ 5961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private DataHeader readDataHeaderForBooleanArray(int expectedLength) { 5971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DataHeader dataHeader = readDataHeader(); 5981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (dataHeader.size < DataHeader.HEADER_SIZE + (dataHeader.numFields + 7) / 8) { 5991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci throw new DeserializationException("Array header is incorrect."); 6001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 6011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (expectedLength != BindingsHelper.UNSPECIFIED_ARRAY_LENGTH 6021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci && dataHeader.numFields != expectedLength) { 6031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci throw new DeserializationException("Incorrect array length. Expected: " + 6041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci expectedLength + ", but got: " + dataHeader.numFields + "."); 6051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 6061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return dataHeader; 6071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 6081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 6091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci /** 6101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * Deserializes a {@link DataHeader} of an array at the given offset. 6111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci */ 6121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private DataHeader readDataHeaderForArray(long elementSize, int expectedLength) { 6131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DataHeader dataHeader = readDataHeader(); 6141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (dataHeader.size < (DataHeader.HEADER_SIZE + elementSize * dataHeader.numFields)) { 6151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci throw new DeserializationException("Array header is incorrect."); 6161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 6171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (expectedLength != BindingsHelper.UNSPECIFIED_ARRAY_LENGTH 6181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci && dataHeader.numFields != expectedLength) { 6191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci throw new DeserializationException("Incorrect array length. Expected: " + 6201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci expectedLength + ", but got: " + dataHeader.numFields + "."); 6211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 6221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return dataHeader; 6231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 6241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 6251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private void validateBufferSize(int offset, int size) { 6261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (mMessage.getData().limit() < offset + size) { 6271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci throw new DeserializationException("Buffer is smaller than expected."); 6281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 6291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 630116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 631