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

// BinaryStream.h: Provides binary serialization of simple types.

#ifndef COMMON_BINARYSTREAM_H_
#define COMMON_BINARYSTREAM_H_

#include <stdint.h>
#include <cstddef>
#include <string>
#include <vector>

#include "common/angleutils.h"
#include "common/mathutil.h"

namespace gl
{
template <typename IntT>
struct PromotedIntegerType
{
    using type = typename std::conditional<
        std::is_signed<IntT>::value,
        typename std::conditional<sizeof(IntT) <= 4, int32_t, int64_t>::type,
        typename std::conditional<sizeof(IntT) <= 4, uint32_t, uint64_t>::type>::type;
};

class BinaryInputStream : angle::NonCopyable
{
  public:
    BinaryInputStream(const void *data, size_t length)
    {
        mError  = false;
        mOffset = 0;
        mData   = static_cast<const uint8_t *>(data);
        mLength = length;
    }

    // readInt will generate an error for bool types
    template <class IntT>
    IntT readInt()
    {
        static_assert(!std::is_same<bool, std::remove_cv<IntT>()>(), "Use readBool");
        using PromotedIntT = typename PromotedIntegerType<IntT>::type;
        PromotedIntT value = 0;
        read(&value);
        ASSERT(angle::IsValueInRangeForNumericType<IntT>(value));
        return static_cast<IntT>(value);
    }

    template <class IntT>
    void readInt(IntT *outValue)
    {
        *outValue = readInt<IntT>();
    }

    template <class IntT, class VectorElementT>
    void readIntVector(std::vector<VectorElementT> *param)
    {
        size_t size = readInt<size_t>();
        param->reserve(size);
        for (size_t index = 0; index < size; ++index)
        {
            param->push_back(readInt<IntT>());
        }
    }

    template <class EnumT>
    EnumT readEnum()
    {
        using UnderlyingType = typename std::underlying_type<EnumT>::type;
        return static_cast<EnumT>(readInt<UnderlyingType>());
    }

    template <class EnumT>
    void readEnum(EnumT *outValue)
    {
        *outValue = readEnum<EnumT>();
    }

    bool readBool()
    {
        int value = 0;
        read(&value);
        return (value > 0);
    }

    void readBool(bool *outValue) { *outValue = readBool(); }

    void readBytes(unsigned char outArray[], size_t count) { read<unsigned char>(outArray, count); }

    std::string readString()
    {
        std::string outString;
        readString(&outString);
        return outString;
    }

    void readString(std::string *v)
    {
        size_t length;
        readInt(&length);

        if (mError)
        {
            return;
        }

        angle::CheckedNumeric<size_t> checkedOffset(mOffset);
        checkedOffset += length;

        if (!checkedOffset.IsValid() || mOffset + length > mLength)
        {
            mError = true;
            return;
        }

        v->assign(reinterpret_cast<const char *>(mData) + mOffset, length);
        mOffset = checkedOffset.ValueOrDie();
    }

    float readFloat()
    {
        float f;
        read(&f, 1);
        return f;
    }

    void skip(size_t length)
    {
        angle::CheckedNumeric<size_t> checkedOffset(mOffset);
        checkedOffset += length;

        if (!checkedOffset.IsValid() || mOffset + length > mLength)
        {
            mError = true;
            return;
        }

        mOffset = checkedOffset.ValueOrDie();
    }

    size_t offset() const { return mOffset; }
    size_t remainingSize() const
    {
        ASSERT(mLength >= mOffset);
        return mLength - mOffset;
    }

    bool error() const { return mError; }

    bool endOfStream() const { return mOffset == mLength; }

    const uint8_t *data() { return mData; }

  private:
    bool mError;
    size_t mOffset;
    const uint8_t *mData;
    size_t mLength;

    template <typename T>
    void read(T *v, size_t num)
    {
        static_assert(std::is_fundamental<T>::value, "T must be a fundamental type.");

        angle::CheckedNumeric<size_t> checkedLength(num);
        checkedLength *= sizeof(T);
        if (!checkedLength.IsValid())
        {
            mError = true;
            return;
        }

        angle::CheckedNumeric<size_t> checkedOffset(mOffset);
        checkedOffset += checkedLength;

        if (!checkedOffset.IsValid() || checkedOffset.ValueOrDie() > mLength)
        {
            mError = true;
            return;
        }

        memcpy(v, mData + mOffset, checkedLength.ValueOrDie());
        mOffset = checkedOffset.ValueOrDie();
    }

    template <typename T>
    void read(T *v)
    {
        read(v, 1);
    }
};

class BinaryOutputStream : angle::NonCopyable
{
  public:
    BinaryOutputStream();
    ~BinaryOutputStream();

    // writeInt also handles bool types
    template <class IntT>
    void writeInt(IntT param)
    {
        static_assert(std::is_integral<IntT>::value, "Not an integral type");
        static_assert(!std::is_same<bool, std::remove_cv<IntT>()>(), "Use writeBool");
        using PromotedIntT = typename PromotedIntegerType<IntT>::type;
        ASSERT(angle::IsValueInRangeForNumericType<PromotedIntT>(param));
        PromotedIntT intValue = static_cast<PromotedIntT>(param);
        write(&intValue, 1);
    }

    // Specialized writeInt for values that can also be exactly -1.
    template <class UintT>
    void writeIntOrNegOne(UintT param)
    {
        if (param == static_cast<UintT>(-1))
        {
            writeInt(-1);
        }
        else
        {
            writeInt(param);
        }
    }

    template <class IntT>
    void writeIntVector(const std::vector<IntT> &param)
    {
        writeInt(param.size());
        for (IntT element : param)
        {
            writeIntOrNegOne(element);
        }
    }

    template <class EnumT>
    void writeEnum(EnumT param)
    {
        using UnderlyingType = typename std::underlying_type<EnumT>::type;
        writeInt<UnderlyingType>(static_cast<UnderlyingType>(param));
    }

    void writeString(const std::string &v)
    {
        writeInt(v.length());
        write(v.c_str(), v.length());
    }

    void writeString(const char *v)
    {
        size_t len = strlen(v);
        writeInt(len);
        write(v, len);
    }

    void writeBytes(const unsigned char *bytes, size_t count) { write(bytes, count); }

    void writeBool(bool value)
    {
        int intValue = value ? 1 : 0;
        write(&intValue, 1);
    }

    void writeFloat(float value) { write(&value, 1); }

    size_t length() const { return mData.size(); }

    const void *data() const { return mData.size() ? &mData[0] : nullptr; }

    const std::vector<uint8_t> &getData() const { return mData; }

  private:
    template <typename T>
    void write(const T *v, size_t num)
    {
        static_assert(std::is_fundamental<T>::value, "T must be a fundamental type.");
        const char *asBytes = reinterpret_cast<const char *>(v);
        mData.insert(mData.end(), asBytes, asBytes + num * sizeof(T));
    }

    std::vector<uint8_t> mData;
};

inline BinaryOutputStream::BinaryOutputStream() {}

inline BinaryOutputStream::~BinaryOutputStream() = default;

}  // namespace gl

#endif  // COMMON_BINARYSTREAM_H_
