1645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Copyright 2014 The Chromium Authors. All rights reserved. 2645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Use of this source code is governed by a BSD-style license that can be 3645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// found in the LICENSE file. 4645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 5645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezpackage org.chromium.mojo.bindings; 6645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 7645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezimport org.chromium.mojo.bindings.Interface.Proxy.Handler; 8645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezimport org.chromium.mojo.system.Core; 9645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezimport org.chromium.mojo.system.Handle; 10645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezimport org.chromium.mojo.system.MessagePipeHandle; 11645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezimport org.chromium.mojo.system.Pair; 12645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 13645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezimport java.nio.ByteBuffer; 14645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezimport java.nio.ByteOrder; 15645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezimport java.nio.charset.Charset; 16645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezimport java.util.ArrayList; 17645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezimport java.util.List; 18645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 19645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez/** 20645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Helper class to encode a mojo struct. It keeps track of the output buffer, resizing it as needed. 21645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * It also keeps track of the associated handles, and the offset of the current data section. 22645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 23645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezpublic class Encoder { 24645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 25645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 26645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Container class for all state that must be shared between the main encoder and any used sub 27645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * encoder. 28645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 29645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private static class EncoderState { 30645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 31645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 32645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * The core used to encode interfaces. 33645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 34645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public final Core core; 35645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 36645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 37645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * The ByteBuffer to which the message will be encoded. 38645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 39645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public ByteBuffer byteBuffer; 40645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 41645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 42645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * The list of encountered handles. 43645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 44645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public final List<Handle> handles = new ArrayList<Handle>(); 45645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 46645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 47645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * The current absolute position for the next data section. 48645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 49645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public int dataEnd; 50645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 51645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 52645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * @param core the |Core| implementation used to generate handles. Only used if the data 53645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * structure being encoded contains interfaces, can be |null| otherwise. 54645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * @param bufferSize A hint on the size of the message. Used to build the initial byte 55645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * buffer. 56645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 57645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private EncoderState(Core core, int bufferSize) { 58645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez assert bufferSize % BindingsHelper.ALIGNMENT == 0; 59645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez this.core = core; 60645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez byteBuffer = ByteBuffer.allocateDirect( 61645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bufferSize > 0 ? bufferSize : INITIAL_BUFFER_SIZE); 62645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez byteBuffer.order(ByteOrder.LITTLE_ENDIAN); 63645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez dataEnd = 0; 64645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 65645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 66645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 67645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Claim the given amount of memory at the end of the buffer, resizing it if needed. 68645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 69645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public void claimMemory(int size) { 70645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez dataEnd += size; 71645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez growIfNeeded(); 72645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 73645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 74645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 75645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Grow the associated ByteBuffer if needed. 76645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 77645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private void growIfNeeded() { 78645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (byteBuffer.capacity() >= dataEnd) { 79645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return; 80645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 81645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez int targetSize = byteBuffer.capacity() * 2; 82645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez while (targetSize < dataEnd) { 83645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez targetSize *= 2; 84645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 85645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ByteBuffer newBuffer = ByteBuffer.allocateDirect(targetSize); 86645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez newBuffer.order(ByteOrder.nativeOrder()); 87645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez byteBuffer.position(0); 88645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez byteBuffer.limit(byteBuffer.capacity()); 89645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez newBuffer.put(byteBuffer); 90645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez byteBuffer = newBuffer; 91645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 92645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 93645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 94645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 95645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Default initial size of the data buffer. This must be a multiple of 8 bytes. 96645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 97645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private static final int INITIAL_BUFFER_SIZE = 1024; 98645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 99645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 100645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Base offset in the byte buffer for writing. 101645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 102645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private int mBaseOffset; 103645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 104645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 105645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * The encoder state shared by the main encoder and all its sub-encoder. 106645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 107645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private final EncoderState mEncoderState; 108645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 109645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 110645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Returns the result message. 111645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 112645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public Message getMessage() { 113645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mEncoderState.byteBuffer.position(0); 114645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mEncoderState.byteBuffer.limit(mEncoderState.dataEnd); 115645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return new Message(mEncoderState.byteBuffer, mEncoderState.handles); 116645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 117645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 118645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 119645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Constructor. 120645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 121645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * @param core the |Core| implementation used to generate handles. Only used if the data 122645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * structure being encoded contains interfaces, can be |null| otherwise. 123645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * @param sizeHint A hint on the size of the message. Used to build the initial byte buffer. 124645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 125645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public Encoder(Core core, int sizeHint) { 126645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez this(new EncoderState(core, sizeHint)); 127645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 128645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 129645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 130645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Private constructor for sub-encoders. 131645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 132645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private Encoder(EncoderState bufferInformation) { 133645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mEncoderState = bufferInformation; 134645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mBaseOffset = bufferInformation.dataEnd; 135645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 136645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 137645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 138645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Returns a new encoder that will append to the current buffer. 139645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 140645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public Encoder getEncoderAtDataOffset(DataHeader dataHeader) { 141645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Encoder result = new Encoder(mEncoderState); 142645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez result.encode(dataHeader); 143645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return result; 144645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 145645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 146645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 147645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Encode a {@link DataHeader} and claim the amount of memory required for the data section 148645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * (resizing the buffer if required). 149645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 150645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public void encode(DataHeader s) { 151645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mEncoderState.claimMemory(BindingsHelper.align(s.size)); 152645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encode(s.size, DataHeader.SIZE_OFFSET); 153645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encode(s.elementsOrVersion, DataHeader.ELEMENTS_OR_VERSION_OFFSET); 154645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 155645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 156645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 157645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Encode a byte at the given offset. 158645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 159645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public void encode(byte v, int offset) { 160645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mEncoderState.byteBuffer.put(mBaseOffset + offset, v); 161645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 162645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 163645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 164645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Encode a boolean at the given offset. 165645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 166645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public void encode(boolean v, int offset, int bit) { 167645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (v) { 168645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez byte encodedValue = mEncoderState.byteBuffer.get(mBaseOffset + offset); 169645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encodedValue |= (byte) (1 << bit); 170645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mEncoderState.byteBuffer.put(mBaseOffset + offset, encodedValue); 171645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 172645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 173645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 174645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 175645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Encode a short at the given offset. 176645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 177645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public void encode(short v, int offset) { 178645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mEncoderState.byteBuffer.putShort(mBaseOffset + offset, v); 179645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 180645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 181645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 182645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Encode an int at the given offset. 183645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 184645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public void encode(int v, int offset) { 185645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mEncoderState.byteBuffer.putInt(mBaseOffset + offset, v); 186645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 187645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 188645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 189645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Encode a float at the given offset. 190645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 191645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public void encode(float v, int offset) { 192645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mEncoderState.byteBuffer.putFloat(mBaseOffset + offset, v); 193645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 194645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 195645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 196645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Encode a long at the given offset. 197645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 198645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public void encode(long v, int offset) { 199645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mEncoderState.byteBuffer.putLong(mBaseOffset + offset, v); 200645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 201645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 202645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 203645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Encode a double at the given offset. 204645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 205645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public void encode(double v, int offset) { 206645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mEncoderState.byteBuffer.putDouble(mBaseOffset + offset, v); 207645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 208645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 209645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 210645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Encode a {@link Struct} at the given offset. 211645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 212645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public void encode(Struct v, int offset, boolean nullable) { 213645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (v == null) { 214645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encodeNullPointer(offset, nullable); 215645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return; 216645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 217645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encodePointerToNextUnclaimedData(offset); 218645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez v.encode(this); 219645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 220645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 221645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 222645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Encode a {@link Union} at the given offset. 223645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 224645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public void encode(Union v, int offset, boolean nullable) { 225645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (v == null && !nullable) { 226645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez throw new SerializationException( 227645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez "Trying to encode a null pointer for a non-nullable type."); 228645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 229645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (v == null) { 230645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encode(0L, offset); 231645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encode(0L, offset + DataHeader.HEADER_SIZE); 232645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return; 233645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 234645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez v.encode(this, offset); 235645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 236645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 237645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 238645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Encodes a String. 239645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 240645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public void encode(String v, int offset, boolean nullable) { 241645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (v == null) { 242645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encodeNullPointer(offset, nullable); 243645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return; 244645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 245645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez final int arrayNullability = nullable 246645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ? BindingsHelper.ARRAY_NULLABLE : BindingsHelper.NOTHING_NULLABLE; 247645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encode(v.getBytes(Charset.forName("utf8")), offset, arrayNullability, 248645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez BindingsHelper.UNSPECIFIED_ARRAY_LENGTH); 249645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 250645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 251645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 252645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Encodes a {@link Handle}. 253645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 254645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public void encode(Handle v, int offset, boolean nullable) { 255645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (v == null || !v.isValid()) { 256645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encodeInvalidHandle(offset, nullable); 257645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } else { 258645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encode(mEncoderState.handles.size(), offset); 259645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mEncoderState.handles.add(v); 260645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 261645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 262645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 263645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 264645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Encode an {@link Interface}. 265645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 266645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public <T extends Interface> void encode(T v, int offset, boolean nullable, 267645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Interface.Manager<T, ?> manager) { 268645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (v == null) { 269645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encodeInvalidHandle(offset, nullable); 270645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encode(0, offset + BindingsHelper.SERIALIZED_HANDLE_SIZE); 271645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return; 272645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 273645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (mEncoderState.core == null) { 274645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez throw new UnsupportedOperationException( 275645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez "The encoder has been created without a Core. It can't encode an interface."); 276645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 277645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // If the instance is a proxy, pass the proxy's handle instead of creating a new stub. 278645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (v instanceof Interface.Proxy) { 279645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Handler handler = ((Interface.Proxy) v).getProxyHandler(); 280645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encode(handler.passHandle(), offset, nullable); 281645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encode(handler.getVersion(), offset + BindingsHelper.SERIALIZED_HANDLE_SIZE); 282645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return; 283645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 284645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Pair<MessagePipeHandle, MessagePipeHandle> handles = 285645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mEncoderState.core.createMessagePipe(null); 286645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez manager.bind(v, handles.first); 287645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encode(handles.second, offset, nullable); 288645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encode(manager.getVersion(), offset + BindingsHelper.SERIALIZED_HANDLE_SIZE); 289645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 290645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 291645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 292645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Encode an {@link InterfaceRequest}. 293645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 294645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public <I extends Interface> void encode(InterfaceRequest<I> v, int offset, boolean nullable) { 295645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (v == null) { 296645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encodeInvalidHandle(offset, nullable); 297645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return; 298645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 299645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (mEncoderState.core == null) { 300645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez throw new UnsupportedOperationException( 301645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez "The encoder has been created without a Core. It can't encode an interface."); 302645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 303645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encode(v.passHandle(), offset, nullable); 304645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 305645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 306645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 307645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Encode an associated interface. Not yet supported. 308645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 309645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public void encode(AssociatedInterfaceNotSupported v, int offset, boolean nullable) { 310645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 311645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 312645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 313645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Encode an associated interface request. Not yet supported. 314645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 315645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public void encode(AssociatedInterfaceRequestNotSupported v, int offset, boolean nullable) { 316645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 317645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 318645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 319645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Returns an {@link Encoder} suitable for encoding an array of pointer of the given length. 320645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 321645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public Encoder encodePointerArray(int length, int offset, int expectedLength) { 322645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return encoderForArray(BindingsHelper.POINTER_SIZE, length, offset, expectedLength); 323645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 324645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 325645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 326645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Returns an {@link Encoder} suitable for encoding an array of union of the given length. 327645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 328645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public Encoder encodeUnionArray(int length, int offset, int expectedLength) { 329645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return encoderForArray(BindingsHelper.UNION_SIZE, length, offset, expectedLength); 330645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 331645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 332645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 333645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Encodes an array of booleans. 334645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 335645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public void encode(boolean[] v, int offset, int arrayNullability, int expectedLength) { 336645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (v == null) { 337645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encodeNullPointer(offset, BindingsHelper.isArrayNullable(arrayNullability)); 338645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return; 339645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 340645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (expectedLength != BindingsHelper.UNSPECIFIED_ARRAY_LENGTH 341645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez && expectedLength != v.length) { 342645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez throw new SerializationException("Trying to encode a fixed array of incorrect length."); 343645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 344645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez byte[] bytes = new byte[(v.length + 7) / BindingsHelper.ALIGNMENT]; 345645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez for (int i = 0; i < bytes.length; ++i) { 346645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez for (int j = 0; j < BindingsHelper.ALIGNMENT; ++j) { 347645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez int booleanIndex = BindingsHelper.ALIGNMENT * i + j; 348645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (booleanIndex < v.length && v[booleanIndex]) { 349645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bytes[i] |= (byte) (1 << j); 350645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 351645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 352645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 353645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encodeByteArray(bytes, v.length, offset); 354645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 355645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 356645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 357645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Encodes an array of bytes. 358645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 359645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public void encode(byte[] v, int offset, int arrayNullability, int expectedLength) { 360645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (v == null) { 361645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encodeNullPointer(offset, BindingsHelper.isArrayNullable(arrayNullability)); 362645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return; 363645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 364645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (expectedLength != BindingsHelper.UNSPECIFIED_ARRAY_LENGTH 365645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez && expectedLength != v.length) { 366645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez throw new SerializationException("Trying to encode a fixed array of incorrect length."); 367645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 368645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encodeByteArray(v, v.length, offset); 369645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 370645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 371645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 372645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Encodes an array of shorts. 373645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 374645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public void encode(short[] v, int offset, int arrayNullability, int expectedLength) { 375645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (v == null) { 376645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encodeNullPointer(offset, BindingsHelper.isArrayNullable(arrayNullability)); 377645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return; 378645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 379645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encoderForArray(2, v.length, offset, expectedLength).append(v); 380645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 381645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 382645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 383645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Encodes an array of ints. 384645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 385645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public void encode(int[] v, int offset, int arrayNullability, int expectedLength) { 386645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (v == null) { 387645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encodeNullPointer(offset, BindingsHelper.isArrayNullable(arrayNullability)); 388645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return; 389645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 390645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encoderForArray(4, v.length, offset, expectedLength).append(v); 391645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 392645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 393645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 394645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Encodes an array of floats. 395645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 396645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public void encode(float[] v, int offset, int arrayNullability, int expectedLength) { 397645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (v == null) { 398645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encodeNullPointer(offset, BindingsHelper.isArrayNullable(arrayNullability)); 399645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return; 400645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 401645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encoderForArray(4, v.length, offset, expectedLength).append(v); 402645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 403645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 404645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 405645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Encodes an array of longs. 406645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 407645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public void encode(long[] v, int offset, int arrayNullability, int expectedLength) { 408645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (v == null) { 409645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encodeNullPointer(offset, BindingsHelper.isArrayNullable(arrayNullability)); 410645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return; 411645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 412645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encoderForArray(8, v.length, offset, expectedLength).append(v); 413645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 414645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 415645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 416645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Encodes an array of doubles. 417645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 418645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public void encode(double[] v, int offset, int arrayNullability, int expectedLength) { 419645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (v == null) { 420645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encodeNullPointer(offset, BindingsHelper.isArrayNullable(arrayNullability)); 421645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return; 422645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 423645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encoderForArray(8, v.length, offset, expectedLength).append(v); 424645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 425645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 426645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 427645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Encodes an array of {@link Handle}. 428645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 429645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public void encode(Handle[] v, int offset, int arrayNullability, int expectedLength) { 430645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (v == null) { 431645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encodeNullPointer(offset, BindingsHelper.isArrayNullable(arrayNullability)); 432645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return; 433645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 434645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Encoder e = encoderForArray( 435645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez BindingsHelper.SERIALIZED_HANDLE_SIZE, v.length, offset, expectedLength); 436645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez for (int i = 0; i < v.length; ++i) { 437645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez e.encode(v[i], DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i, 438645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez BindingsHelper.isElementNullable(arrayNullability)); 439645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 440645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 441645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 442645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 443645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Encodes an array of {@link Interface}. 444645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 445645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public <T extends Interface> void encode(T[] v, int offset, int arrayNullability, 446645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez int expectedLength, Interface.Manager<T, ?> manager) { 447645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (v == null) { 448645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encodeNullPointer(offset, BindingsHelper.isArrayNullable(arrayNullability)); 449645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return; 450645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 451645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Encoder e = encoderForArray( 452645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez BindingsHelper.SERIALIZED_INTERFACE_SIZE, v.length, offset, expectedLength); 453645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez for (int i = 0; i < v.length; ++i) { 454645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez e.encode(v[i], DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_INTERFACE_SIZE * i, 455645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez BindingsHelper.isElementNullable(arrayNullability), manager); 456645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 457645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 458645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 459645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public Encoder encoderForMap(int offset) { 460645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encodePointerToNextUnclaimedData(offset); 461645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return getEncoderAtDataOffset(BindingsHelper.MAP_STRUCT_HEADER); 462645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 463645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 464645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 465645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Encodes a pointer to the next unclaimed memory and returns an encoder suitable to encode an 466645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * union at this location. 467645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 468645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public Encoder encoderForUnionPointer(int offset) { 469645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encodePointerToNextUnclaimedData(offset); 470645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Encoder result = new Encoder(mEncoderState); 471645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez result.mEncoderState.claimMemory(16); 472645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return result; 473645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 474645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 475645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 476645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Encodes an array of {@link InterfaceRequest}. 477645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 478645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public <I extends Interface> void encode(InterfaceRequest<I>[] v, int offset, 479645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez int arrayNullability, int expectedLength) { 480645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (v == null) { 481645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encodeNullPointer(offset, BindingsHelper.isArrayNullable(arrayNullability)); 482645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return; 483645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 484645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Encoder e = encoderForArray( 485645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez BindingsHelper.SERIALIZED_HANDLE_SIZE, v.length, offset, expectedLength); 486645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez for (int i = 0; i < v.length; ++i) { 487645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez e.encode(v[i], DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i, 488645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez BindingsHelper.isElementNullable(arrayNullability)); 489645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 490645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 491645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 492645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 493645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Encodes an array of associated interfaces. Not yet supported. 494645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 495645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public void encode(AssociatedInterfaceNotSupported[] v, int offset, int arrayNullability, 496645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez int expectedLength) {} 497645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 498645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 499645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Encodes an array of associated interface requests. Not yet supported. 500645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 501645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public void encode(AssociatedInterfaceRequestNotSupported[] v, int offset, int arrayNullability, 502645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez int expectedLength) {} 503645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 504645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 505645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Encodes a <code>null</code> pointer iff the object is nullable, raises an exception 506645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * otherwise. 507645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 508645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public void encodeNullPointer(int offset, boolean nullable) { 509645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!nullable) { 510645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez throw new SerializationException( 511645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez "Trying to encode a null pointer for a non-nullable type."); 512645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 513645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mEncoderState.byteBuffer.putLong(mBaseOffset + offset, 0); 514645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 515645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 516645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 517645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Encodes an invalid handle iff the object is nullable, raises an exception otherwise. 518645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 519645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public void encodeInvalidHandle(int offset, boolean nullable) { 520645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!nullable) { 521645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez throw new SerializationException( 522645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez "Trying to encode an invalid handle for a non-nullable type."); 523645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 524645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mEncoderState.byteBuffer.putInt(mBaseOffset + offset, -1); 525645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 526645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 527645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 528645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Claim the given amount of memory at the end of the buffer, resizing it if needed. 529645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 530645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez void claimMemory(int size) { 531645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mEncoderState.claimMemory(BindingsHelper.align(size)); 532645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 533645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 534645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private void encodePointerToNextUnclaimedData(int offset) { 535645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encode((long) mEncoderState.dataEnd - (mBaseOffset + offset), offset); 536645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 537645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 538645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private Encoder encoderForArray( 539645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez int elementSizeInByte, int length, int offset, int expectedLength) { 540645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (expectedLength != BindingsHelper.UNSPECIFIED_ARRAY_LENGTH 541645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez && expectedLength != length) { 542645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez throw new SerializationException("Trying to encode a fixed array of incorrect length."); 543645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 544645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return encoderForArrayByTotalSize(length * elementSizeInByte, length, offset); 545645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 546645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 547645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private Encoder encoderForArrayByTotalSize(int byteSize, int length, int offset) { 548645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encodePointerToNextUnclaimedData(offset); 549645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return getEncoderAtDataOffset( 550645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez new DataHeader(DataHeader.HEADER_SIZE + byteSize, length)); 551645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 552645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 553645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private void encodeByteArray(byte[] bytes, int length, int offset) { 554645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez encoderForArrayByTotalSize(bytes.length, length, offset).append(bytes); 555645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 556645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 557645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private void append(byte[] v) { 558645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mEncoderState.byteBuffer.position(mBaseOffset + DataHeader.HEADER_SIZE); 559645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mEncoderState.byteBuffer.put(v); 560645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 561645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 562645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private void append(short[] v) { 563645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mEncoderState.byteBuffer.position(mBaseOffset + DataHeader.HEADER_SIZE); 564645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mEncoderState.byteBuffer.asShortBuffer().put(v); 565645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 566645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 567645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private void append(int[] v) { 568645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mEncoderState.byteBuffer.position(mBaseOffset + DataHeader.HEADER_SIZE); 569645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mEncoderState.byteBuffer.asIntBuffer().put(v); 570645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 571645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 572645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private void append(float[] v) { 573645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mEncoderState.byteBuffer.position(mBaseOffset + DataHeader.HEADER_SIZE); 574645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mEncoderState.byteBuffer.asFloatBuffer().put(v); 575645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 576645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 577645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private void append(double[] v) { 578645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mEncoderState.byteBuffer.position(mBaseOffset + DataHeader.HEADER_SIZE); 579645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mEncoderState.byteBuffer.asDoubleBuffer().put(v); 580645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 581645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 582645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private void append(long[] v) { 583645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mEncoderState.byteBuffer.position(mBaseOffset + DataHeader.HEADER_SIZE); 584645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mEncoderState.byteBuffer.asLongBuffer().put(v); 585645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 586645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 587645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 588