// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.mojo.bindings;

import org.chromium.mojo.bindings.Interface.Proxy;
import org.chromium.mojo.system.DataPipe;
import org.chromium.mojo.system.Handle;
import org.chromium.mojo.system.InvalidHandle;
import org.chromium.mojo.system.MessagePipeHandle;
import org.chromium.mojo.system.SharedBufferHandle;
import org.chromium.mojo.system.UntypedHandle;

import java.nio.ByteOrder;
import java.nio.charset.Charset;

/**
 * A Decoder is a helper class for deserializing a mojo struct. It enables deserialization of basic
 * types from a {@link Message} object at a given offset into it's byte buffer.
 */
public class Decoder {

    /**
     * Helper class to validate the decoded message.
     */
    static final class Validator {

        /**
         * Minimal value for the next handle to deserialize.
         */
        private int mMinNextClaimedHandle;
        /**
         * Minimal value of the start of the next memory to claim.
         */
        private long mMinNextMemory;
        /**
         * The current nesting level when decoding.
         */
        private long mStackDepth;

        /**
         * The maximal memory accessible.
         */
        private final long mMaxMemory;

        /**
         * The number of handles in the message.
         */
        private final long mNumberOfHandles;

        /**
         * The maximum nesting level when decoding.
         */
        private static final int MAX_RECURSION_DEPTH = 100;

        /**
         * Constructor.
         */
        Validator(long maxMemory, int numberOfHandles) {
            mMaxMemory = maxMemory;
            mNumberOfHandles = numberOfHandles;
            mStackDepth = 0;
        }

        public void claimHandle(int handle) {
            if (handle < mMinNextClaimedHandle) {
                throw new DeserializationException(
                        "Trying to access handle out of order.");
            }
            if (handle >= mNumberOfHandles) {
                throw new DeserializationException("Trying to access non present handle.");
            }
            mMinNextClaimedHandle = handle + 1;
        }

        public void claimMemory(long start, long end) {
            if (start % BindingsHelper.ALIGNMENT != 0) {
                throw new DeserializationException("Incorrect starting alignment: " + start + ".");
            }
            if (start < mMinNextMemory) {
                throw new DeserializationException("Trying to access memory out of order.");
            }
            if (end < start) {
                throw new DeserializationException("Incorrect memory range.");
            }
            if (end > mMaxMemory) {
                throw new DeserializationException("Trying to access out of range memory.");
            }
            mMinNextMemory = BindingsHelper.align(end);
        }

        public void increaseStackDepth() {
            ++mStackDepth;
            if (mStackDepth >= MAX_RECURSION_DEPTH) {
                throw new DeserializationException("Recursion depth limit exceeded.");
            }
        }

        public void decreaseStackDepth() {
            --mStackDepth;
        }
    }

    /**
     * The message to deserialize from.
     */
    private final Message mMessage;

    /**
     * The base offset in the byte buffer.
     */
    private final int mBaseOffset;

    /**
     * Validator for the decoded message.
     */
    private final Validator mValidator;

    /**
     * Constructor.
     *
     * @param message The message to decode.
     */
    public Decoder(Message message) {
        this(message, new Validator(message.getData().limit(), message.getHandles().size()), 0);
    }

    private Decoder(Message message, Validator validator, int baseOffset) {
        mMessage = message;
        mMessage.getData().order(ByteOrder.LITTLE_ENDIAN);
        mBaseOffset = baseOffset;
        mValidator = validator;
    }

    /**
     * Deserializes a {@link DataHeader} at the current position.
     */
    public DataHeader readDataHeader() {
        // Claim the memory for the header.
        mValidator.claimMemory(mBaseOffset, mBaseOffset + DataHeader.HEADER_SIZE);
        DataHeader result = readDataHeaderAtOffset(0, false);
        // Claim the rest of the memory.
        mValidator.claimMemory(mBaseOffset + DataHeader.HEADER_SIZE, mBaseOffset + result.size);
        return result;
    }

    /**
     * Deserializes a {@link DataHeader} for an union at the given offset.
     */
    public DataHeader readDataHeaderForUnion(int offset) {
        DataHeader result = readDataHeaderAtOffset(offset, true);
        if (result.size == 0) {
            if (result.elementsOrVersion != 0) {
                throw new DeserializationException(
                        "Unexpected version tag for a null union. Expecting 0, found: "
                        + result.elementsOrVersion);
            }
        } else if (result.size != BindingsHelper.UNION_SIZE) {
            throw new DeserializationException(
                    "Unexpected size of an union. The size must be 0 for a null union, or 16 for "
                    + "a non-null union.");
        }
        return result;
    }

    /**
     * @returns a decoder suitable to decode an union defined as the root object of a message.
     */
    public Decoder decoderForSerializedUnion() {
        mValidator.claimMemory(0, BindingsHelper.UNION_SIZE);
        return this;
    }

    /**
     * Deserializes a {@link DataHeader} at the given offset.
     */
    private DataHeader readDataHeaderAtOffset(int offset, boolean isUnion) {
        int size = readInt(offset + DataHeader.SIZE_OFFSET);
        int elementsOrVersion = readInt(offset + DataHeader.ELEMENTS_OR_VERSION_OFFSET);
        if (size < 0) {
            throw new DeserializationException(
                    "Negative size. Unsigned integers are not valid for java.");
        }
        if (elementsOrVersion < 0 && (!isUnion || elementsOrVersion != -1)) {
            throw new DeserializationException(
                    "Negative elements or version. Unsigned integers are not valid for java.");
        }

        return new DataHeader(size, elementsOrVersion);
    }

    public DataHeader readAndValidateDataHeader(DataHeader[] versionArray) {
        DataHeader header = readDataHeader();
        int maxVersionIndex = versionArray.length - 1;
        if (header.elementsOrVersion <= versionArray[maxVersionIndex].elementsOrVersion) {
            DataHeader referenceHeader = null;
            for (int index = maxVersionIndex; index >= 0; index--) {
                DataHeader dataHeader = versionArray[index];
                if (header.elementsOrVersion >= dataHeader.elementsOrVersion) {
                    referenceHeader = dataHeader;
                    break;
                }
            }
            if (referenceHeader == null || referenceHeader.size != header.size) {
                throw new DeserializationException(
                        "Header doesn't correspond to any known version.");
            }
        } else {
            if (header.size < versionArray[maxVersionIndex].size) {
                throw new DeserializationException("Message newer than the last known version"
                        + " cannot be shorter than required by the last known version.");
            }
        }
        return header;
    }

    /**
     * Deserializes a {@link DataHeader} at the given offset and checks if it is correct for an
     * array where elements are pointers.
     */
    public DataHeader readDataHeaderForPointerArray(int expectedLength) {
        return readDataHeaderForArray(BindingsHelper.POINTER_SIZE, expectedLength);
    }

    /**
     * Deserializes a {@link DataHeader} at the given offset and checks if it is correct for an
     * array where elements are unions.
     */
    public DataHeader readDataHeaderForUnionArray(int expectedLength) {
        return readDataHeaderForArray(BindingsHelper.UNION_SIZE, expectedLength);
    }

    /**
     * Deserializes a {@link DataHeader} at the given offset and checks if it is correct for a map.
     */
    public void readDataHeaderForMap() {
        DataHeader si = readDataHeader();
        if (si.size != BindingsHelper.MAP_STRUCT_HEADER.size) {
            throw new DeserializationException(
                    "Incorrect header for map. The size is incorrect.");
        }
        if (si.elementsOrVersion != BindingsHelper.MAP_STRUCT_HEADER.elementsOrVersion) {
            throw new DeserializationException(
                    "Incorrect header for map. The version is incorrect.");
        }
    }

    /**
     * Deserializes a byte at the given offset.
     */
    public byte readByte(int offset) {
        validateBufferSize(offset, 1);
        return mMessage.getData().get(mBaseOffset + offset);
    }

    /**
     * Deserializes a boolean at the given offset, re-using any partially read byte.
     */
    public boolean readBoolean(int offset, int bit) {
        validateBufferSize(offset, 1);
        return (readByte(offset) & (1 << bit)) != 0;
    }

    /**
     * Deserializes a short at the given offset.
     */
    public short readShort(int offset) {
        validateBufferSize(offset, 2);
        return mMessage.getData().getShort(mBaseOffset + offset);
    }

    /**
     * Deserializes an int at the given offset.
     */
    public int readInt(int offset) {
        validateBufferSize(offset, 4);
        return mMessage.getData().getInt(mBaseOffset + offset);
    }

    /**
     * Deserializes a float at the given offset.
     */
    public float readFloat(int offset) {
        validateBufferSize(offset, 4);
        return mMessage.getData().getFloat(mBaseOffset + offset);
    }

    /**
     * Deserializes a long at the given offset.
     */
    public long readLong(int offset) {
        validateBufferSize(offset, 8);
        return mMessage.getData().getLong(mBaseOffset + offset);
    }

    /**
     * Deserializes a double at the given offset.
     */
    public double readDouble(int offset) {
        validateBufferSize(offset, 8);
        return mMessage.getData().getDouble(mBaseOffset + offset);
    }

    /**
     * Deserializes a pointer at the given offset. Returns a Decoder suitable to decode the content
     * of the pointer.
     */
    public Decoder readPointer(int offset, boolean nullable) {
        int basePosition = mBaseOffset + offset;
        long pointerOffset = readLong(offset);
        if (pointerOffset == 0) {
            if (!nullable) {
                throw new DeserializationException(
                        "Trying to decode null pointer for a non-nullable type.");
            }
            return null;
        }
        int newPosition = (int) (basePosition + pointerOffset);
        // The method |getDecoderAtPosition| will validate that the pointer address is valid.
        return getDecoderAtPosition(newPosition);

    }

    /**
     * Deserializes an array of boolean at the given offset.
     */
    public boolean[] readBooleans(int offset, int arrayNullability, int expectedLength) {
        Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
        if (d == null) {
            return null;
        }
        DataHeader si = d.readDataHeaderForBooleanArray(expectedLength);
        byte[] bytes = new byte[(si.elementsOrVersion + 7) / BindingsHelper.ALIGNMENT];
        d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE);
        d.mMessage.getData().get(bytes);
        boolean[] result = new boolean[si.elementsOrVersion];
        for (int i = 0; i < bytes.length; ++i) {
            for (int j = 0; j < BindingsHelper.ALIGNMENT; ++j) {
                int booleanIndex = i * BindingsHelper.ALIGNMENT + j;
                if (booleanIndex < result.length) {
                    result[booleanIndex] = (bytes[i] & (1 << j)) != 0;
                }
            }
        }
        return result;
    }

    /**
     * Deserializes an array of bytes at the given offset.
     */
    public byte[] readBytes(int offset, int arrayNullability, int expectedLength) {
        Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
        if (d == null) {
            return null;
        }
        DataHeader si = d.readDataHeaderForArray(1, expectedLength);
        byte[] result = new byte[si.elementsOrVersion];
        d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE);
        d.mMessage.getData().get(result);
        return result;
    }

    /**
     * Deserializes an array of shorts at the given offset.
     */
    public short[] readShorts(int offset, int arrayNullability, int expectedLength) {
        Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
        if (d == null) {
            return null;
        }
        DataHeader si = d.readDataHeaderForArray(2, expectedLength);
        short[] result = new short[si.elementsOrVersion];
        d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE);
        d.mMessage.getData().asShortBuffer().get(result);
        return result;
    }

    /**
     * Deserializes an array of ints at the given offset.
     */
    public int[] readInts(int offset, int arrayNullability, int expectedLength) {
        Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
        if (d == null) {
            return null;
        }
        DataHeader si = d.readDataHeaderForArray(4, expectedLength);
        int[] result = new int[si.elementsOrVersion];
        d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE);
        d.mMessage.getData().asIntBuffer().get(result);
        return result;
    }

    /**
     * Deserializes an array of floats at the given offset.
     */
    public float[] readFloats(int offset, int arrayNullability, int expectedLength) {
        Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
        if (d == null) {
            return null;
        }
        DataHeader si = d.readDataHeaderForArray(4, expectedLength);
        float[] result = new float[si.elementsOrVersion];
        d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE);
        d.mMessage.getData().asFloatBuffer().get(result);
        return result;
    }

    /**
     * Deserializes an array of longs at the given offset.
     */
    public long[] readLongs(int offset, int arrayNullability, int expectedLength) {
        Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
        if (d == null) {
            return null;
        }
        DataHeader si = d.readDataHeaderForArray(8, expectedLength);
        long[] result = new long[si.elementsOrVersion];
        d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE);
        d.mMessage.getData().asLongBuffer().get(result);
        return result;
    }

    /**
     * Deserializes an array of doubles at the given offset.
     */
    public double[] readDoubles(int offset, int arrayNullability, int expectedLength) {
        Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
        if (d == null) {
            return null;
        }
        DataHeader si = d.readDataHeaderForArray(8, expectedLength);
        double[] result = new double[si.elementsOrVersion];
        d.mMessage.getData().position(d.mBaseOffset + DataHeader.HEADER_SIZE);
        d.mMessage.getData().asDoubleBuffer().get(result);
        return result;
    }

    /**
     * Deserializes an |Handle| at the given offset.
     */
    public Handle readHandle(int offset, boolean nullable) {
        int index = readInt(offset);
        if (index == -1) {
            if (!nullable) {
                throw new DeserializationException(
                        "Trying to decode an invalid handle for a non-nullable type.");
            }
            return InvalidHandle.INSTANCE;
        }
        mValidator.claimHandle(index);
        return mMessage.getHandles().get(index);
    }

    /**
     * Deserializes an |UntypedHandle| at the given offset.
     */
    public UntypedHandle readUntypedHandle(int offset, boolean nullable) {
        return readHandle(offset, nullable).toUntypedHandle();
    }

    /**
     * Deserializes a |ConsumerHandle| at the given offset.
     */
    public DataPipe.ConsumerHandle readConsumerHandle(int offset, boolean nullable) {
        return readUntypedHandle(offset, nullable).toDataPipeConsumerHandle();
    }

    /**
     * Deserializes a |ProducerHandle| at the given offset.
     */
    public DataPipe.ProducerHandle readProducerHandle(int offset, boolean nullable) {
        return readUntypedHandle(offset, nullable).toDataPipeProducerHandle();
    }

    /**
     * Deserializes a |MessagePipeHandle| at the given offset.
     */
    public MessagePipeHandle readMessagePipeHandle(int offset, boolean nullable) {
        return readUntypedHandle(offset, nullable).toMessagePipeHandle();
    }

    /**
     * Deserializes a |SharedBufferHandle| at the given offset.
     */
    public SharedBufferHandle readSharedBufferHandle(int offset, boolean nullable) {
        return readUntypedHandle(offset, nullable).toSharedBufferHandle();
    }

    /**
     * Deserializes an interface at the given offset.
     *
     * @return a proxy to the service.
     */
    public <P extends Proxy> P readServiceInterface(int offset, boolean nullable,
            Interface.Manager<?, P> manager) {
        MessagePipeHandle handle = readMessagePipeHandle(offset, nullable);
        if (!handle.isValid()) {
            return null;
        }
        int version = readInt(offset + BindingsHelper.SERIALIZED_HANDLE_SIZE);
        return manager.attachProxy(handle, version);
    }

    /**
     * Deserializes a |InterfaceRequest| at the given offset.
     */
    public <I extends Interface> InterfaceRequest<I> readInterfaceRequest(int offset,
            boolean nullable) {
        MessagePipeHandle handle = readMessagePipeHandle(offset, nullable);
        if (handle == null) {
            return null;
        }
        return new InterfaceRequest<I>(handle);
    }

    /**
     * Deserializes an associated interface at the given offset. Not yet supported.
     */
    public AssociatedInterfaceNotSupported readAssociatedServiceInterfaceNotSupported(int offset,
            boolean nullable) {
        return null;
    }

    /**
     * Deserializes an associated interface request at the given offset. Not yet supported.
     */
    public AssociatedInterfaceRequestNotSupported readAssociatedInterfaceRequestNotSupported(
            int offset, boolean nullable) {
        return null;
    }

    /**
     * Deserializes a string at the given offset.
     */
    public String readString(int offset, boolean nullable) {
        final int arrayNullability = nullable ? BindingsHelper.ARRAY_NULLABLE : 0;
        byte[] bytes = readBytes(offset, arrayNullability, BindingsHelper.UNSPECIFIED_ARRAY_LENGTH);
        if (bytes == null) {
            return null;
        }
        return new String(bytes, Charset.forName("utf8"));
    }

    /**
     * Deserializes an array of |Handle| at the given offset.
     */
    public Handle[] readHandles(int offset, int arrayNullability, int expectedLength) {
        Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
        if (d == null) {
            return null;
        }
        DataHeader si = d.readDataHeaderForArray(4, expectedLength);
        Handle[] result = new Handle[si.elementsOrVersion];
        for (int i = 0; i < result.length; ++i) {
            result[i] = d.readHandle(
                    DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i,
                    BindingsHelper.isElementNullable(arrayNullability));
        }
        return result;
    }

    /**
     * Deserializes an array of |UntypedHandle| at the given offset.
     */
    public UntypedHandle[] readUntypedHandles(
            int offset, int arrayNullability, int expectedLength) {
        Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
        if (d == null) {
            return null;
        }
        DataHeader si = d.readDataHeaderForArray(4, expectedLength);
        UntypedHandle[] result = new UntypedHandle[si.elementsOrVersion];
        for (int i = 0; i < result.length; ++i) {
            result[i] = d.readUntypedHandle(
                    DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i,
                    BindingsHelper.isElementNullable(arrayNullability));
        }
        return result;
    }

    /**
     * Deserializes an array of |ConsumerHandle| at the given offset.
     */
    public DataPipe.ConsumerHandle[] readConsumerHandles(
            int offset, int arrayNullability, int expectedLength) {
        Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
        if (d == null) {
            return null;
        }
        DataHeader si = d.readDataHeaderForArray(4, expectedLength);
        DataPipe.ConsumerHandle[] result = new DataPipe.ConsumerHandle[si.elementsOrVersion];
        for (int i = 0; i < result.length; ++i) {
            result[i] = d.readConsumerHandle(
                    DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i,
                    BindingsHelper.isElementNullable(arrayNullability));
        }
        return result;
    }

    /**
     * Deserializes an array of |ProducerHandle| at the given offset.
     */
    public DataPipe.ProducerHandle[] readProducerHandles(
            int offset, int arrayNullability, int expectedLength) {
        Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
        if (d == null) {
            return null;
        }
        DataHeader si = d.readDataHeaderForArray(4, expectedLength);
        DataPipe.ProducerHandle[] result = new DataPipe.ProducerHandle[si.elementsOrVersion];
        for (int i = 0; i < result.length; ++i) {
            result[i] = d.readProducerHandle(
                    DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i,
                    BindingsHelper.isElementNullable(arrayNullability));
        }
        return result;

    }

    /**
     * Deserializes an array of |MessagePipeHandle| at the given offset.
     */
    public MessagePipeHandle[] readMessagePipeHandles(
            int offset, int arrayNullability, int expectedLength) {
        Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
        if (d == null) {
            return null;
        }
        DataHeader si = d.readDataHeaderForArray(4, expectedLength);
        MessagePipeHandle[] result = new MessagePipeHandle[si.elementsOrVersion];
        for (int i = 0; i < result.length; ++i) {
            result[i] = d.readMessagePipeHandle(
                    DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i,
                    BindingsHelper.isElementNullable(arrayNullability));
        }
        return result;

    }

    /**
     * Deserializes an array of |SharedBufferHandle| at the given offset.
     */
    public SharedBufferHandle[] readSharedBufferHandles(
            int offset, int arrayNullability, int expectedLength) {
        Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
        if (d == null) {
            return null;
        }
        DataHeader si = d.readDataHeaderForArray(4, expectedLength);
        SharedBufferHandle[] result = new SharedBufferHandle[si.elementsOrVersion];
        for (int i = 0; i < result.length; ++i) {
            result[i] = d.readSharedBufferHandle(
                    DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i,
                    BindingsHelper.isElementNullable(arrayNullability));
        }
        return result;

    }

    /**
     * Deserializes an array of |ServiceHandle| at the given offset.
     */
    public <S extends Interface, P extends Proxy> S[] readServiceInterfaces(
            int offset, int arrayNullability, int expectedLength, Interface.Manager<S, P> manager) {
        Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
        if (d == null) {
            return null;
        }
        DataHeader si =
                d.readDataHeaderForArray(BindingsHelper.SERIALIZED_INTERFACE_SIZE, expectedLength);
        S[] result = manager.buildArray(si.elementsOrVersion);
        for (int i = 0; i < result.length; ++i) {
            // This cast is necessary because java 6 doesn't handle wildcard correctly when using
            // Manager<S, ? extends S>
            @SuppressWarnings("unchecked")
            S value = (S) d.readServiceInterface(
                    DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_INTERFACE_SIZE * i,
                    BindingsHelper.isElementNullable(arrayNullability), manager);
            result[i] = value;
        }
        return result;
    }

    /**
     * Deserializes an array of |InterfaceRequest| at the given offset.
     */
    public <I extends Interface> InterfaceRequest<I>[] readInterfaceRequests(
            int offset, int arrayNullability, int expectedLength) {
        Decoder d = readPointer(offset, BindingsHelper.isArrayNullable(arrayNullability));
        if (d == null) {
            return null;
        }
        DataHeader si = d.readDataHeaderForArray(4, expectedLength);
        @SuppressWarnings("unchecked")
        InterfaceRequest<I>[] result = new InterfaceRequest[si.elementsOrVersion];
        for (int i = 0; i < result.length; ++i) {
            result[i] = d.readInterfaceRequest(
                    DataHeader.HEADER_SIZE + BindingsHelper.SERIALIZED_HANDLE_SIZE * i,
                    BindingsHelper.isElementNullable(arrayNullability));
        }
        return result;
    }

    /**
     * Deserializes an array of associated interfaces at the given offset. Not yet supported.
     */
    public AssociatedInterfaceNotSupported[] readAssociatedServiceInterfaceNotSupporteds(
            int offset, int arrayNullability, int expectedLength) {
        return null;
    }

    /**
     * Deserializes an array of associated interface requests at the given offset. Not yet
     * supported.
     */
    public AssociatedInterfaceRequestNotSupported[] readAssociatedInterfaceRequestNotSupporteds(
            int offset, int arrayNullability, int expectedLength) {
        return null;
    }

    /**
     * Returns a view of this decoder at the offset |offset|.
     */
    private Decoder getDecoderAtPosition(int offset) {
        return new Decoder(mMessage, mValidator, offset);
    }

    /**
     * Deserializes a {@link DataHeader} at the given offset and checks if it is correct for an
     * array of booleans.
     */
    private DataHeader readDataHeaderForBooleanArray(int expectedLength) {
        DataHeader dataHeader = readDataHeader();
        if (dataHeader.size < DataHeader.HEADER_SIZE + (dataHeader.elementsOrVersion + 7) / 8) {
            throw new DeserializationException("Array header is incorrect.");
        }
        if (expectedLength != BindingsHelper.UNSPECIFIED_ARRAY_LENGTH
                && dataHeader.elementsOrVersion != expectedLength) {
            throw new DeserializationException("Incorrect array length. Expected: " + expectedLength
                    + ", but got: " + dataHeader.elementsOrVersion + ".");
        }
        return dataHeader;
    }

    /**
     * Deserializes a {@link DataHeader} of an array at the given offset.
     */
    private DataHeader readDataHeaderForArray(long elementSize, int expectedLength) {
        DataHeader dataHeader = readDataHeader();
        if (dataHeader.size
                < (DataHeader.HEADER_SIZE + elementSize * dataHeader.elementsOrVersion)) {
            throw new DeserializationException("Array header is incorrect.");
        }
        if (expectedLength != BindingsHelper.UNSPECIFIED_ARRAY_LENGTH
                && dataHeader.elementsOrVersion != expectedLength) {
            throw new DeserializationException("Incorrect array length. Expected: " + expectedLength
                    + ", but got: " + dataHeader.elementsOrVersion + ".");
        }
        return dataHeader;
    }

    private void validateBufferSize(int offset, int size) {
        if (mMessage.getData().limit() < offset + size) {
            throw new DeserializationException("Buffer is smaller than expected.");
        }
    }

    public void increaseStackDepth() {
        mValidator.increaseStackDepth();
    }

    public void decreaseStackDepth() {
        mValidator.decreaseStackDepth();
    }
}
