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