/*
 *    Copyright (c) 2017, The OpenThread Authors.
 *    All rights reserved.
 *
 *    Redistribution and use in source and binary forms, with or without
 *    modification, are permitted provided that the following conditions are met:
 *    1. Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *    2. Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *    3. Neither the name of the copyright holder nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 *    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 *    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
 *    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 *    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 *    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * @file
 *   This file implements a spinel decoder.
 */

#include <openthread/config.h>

#include "spinel_decoder.hpp"

#include "common/code_utils.hpp"
#include "common/string.hpp"

namespace ot {
namespace Ncp {

SpinelDecoder::SpinelDecoder(void)
    : mFrame(NULL)
    , mLength(0)
    , mIndex(0)
    , mEnd(0)
    , mNumOpenStructs(0)
    , mSavedNumOpenStructs(0)
    , mSavedIndex(0)
    , mSavedEnd(0)
{
}

void SpinelDecoder::Init(const uint8_t *aFrame, uint16_t aLength)
{
    mFrame  = aFrame;
    mLength = (mFrame != NULL) ? aLength : 0;

    Reset();
    ClearSavedPosition();
}

void SpinelDecoder::Reset(void)
{
    mIndex          = 0;
    mEnd            = mLength;
    mNumOpenStructs = 0;
    ClearSavedPosition();
}

otError SpinelDecoder::ReadBool(bool &aBool)
{
    otError error = OT_ERROR_NONE;
    uint8_t byte;

    SuccessOrExit(error = ReadUint8(byte));

    // Boolean value are encoded in 8-bits as either 0x00 or 0x01. All other values are illegal.
    if (byte == 0x00)
    {
        aBool = false;
    }
    else if (byte == 0x01)
    {
        aBool = true;
    }
    else
    {
        error = OT_ERROR_PARSE;
    }

exit:
    return error;
}

otError SpinelDecoder::ReadUint8(uint8_t &aUint8)
{
    otError error = OT_ERROR_NONE;

    VerifyOrExit(mIndex + sizeof(uint8_t) <= mEnd, error = OT_ERROR_PARSE);
    aUint8 = mFrame[mIndex];
    mIndex += sizeof(uint8_t);

exit:
    return error;
}

otError SpinelDecoder::ReadInt8(int8_t &aInt8)
{
    otError error = OT_ERROR_NONE;
    uint8_t byte;

    SuccessOrExit(error = ReadUint8(byte));
    aInt8 = static_cast<int8_t>(byte);

exit:
    return error;
}

otError SpinelDecoder::ReadUint16(uint16_t &aUint16)
{
    otError error = OT_ERROR_NONE;

    VerifyOrExit(mIndex + sizeof(uint16_t) <= mEnd, error = OT_ERROR_PARSE);

    aUint16 = static_cast<uint16_t>(mFrame[mIndex] | (mFrame[mIndex + 1] << 8));

    mIndex += sizeof(uint16_t);

exit:
    return error;
}

otError SpinelDecoder::ReadInt16(int16_t &aInt16)
{
    otError  error = OT_ERROR_NONE;
    uint16_t u16;

    SuccessOrExit(error = ReadUint16(u16));
    aInt16 = static_cast<int16_t>(u16);

exit:
    return error;
}

otError SpinelDecoder::ReadUint32(uint32_t &aUint32)
{
    otError error = OT_ERROR_NONE;

    VerifyOrExit(mIndex + sizeof(uint32_t) <= mEnd, error = OT_ERROR_PARSE);

    aUint32 = ((static_cast<uint32_t>(mFrame[mIndex + 0]) << 0) | (static_cast<uint32_t>(mFrame[mIndex + 1]) << 8) |
               (static_cast<uint32_t>(mFrame[mIndex + 2]) << 16) | (static_cast<uint32_t>(mFrame[mIndex + 3]) << 24));

    mIndex += sizeof(uint32_t);

exit:
    return error;
}

otError SpinelDecoder::ReadInt32(int32_t &aInt32)
{
    otError  error = OT_ERROR_NONE;
    uint32_t u32;

    SuccessOrExit(error = ReadUint32(u32));
    aInt32 = static_cast<int32_t>(u32);

exit:
    return error;
}

otError SpinelDecoder::ReadUint64(uint64_t &aUint64)
{
    otError error = OT_ERROR_NONE;

    VerifyOrExit(mIndex + sizeof(uint64_t) <= mEnd, error = OT_ERROR_PARSE);

    aUint64 = ((static_cast<uint64_t>(mFrame[mIndex + 0]) << 0) | (static_cast<uint64_t>(mFrame[mIndex + 1]) << 8) |
               (static_cast<uint64_t>(mFrame[mIndex + 2]) << 16) | (static_cast<uint64_t>(mFrame[mIndex + 3]) << 24) |
               (static_cast<uint64_t>(mFrame[mIndex + 4]) << 32) | (static_cast<uint64_t>(mFrame[mIndex + 5]) << 40) |
               (static_cast<uint64_t>(mFrame[mIndex + 6]) << 48) | (static_cast<uint64_t>(mFrame[mIndex + 7]) << 56));

    mIndex += sizeof(uint64_t);

exit:
    return error;
}

otError SpinelDecoder::ReadInt64(int64_t &aInt64)
{
    otError  error = OT_ERROR_NONE;
    uint64_t u64;

    SuccessOrExit(error = ReadUint64(u64));
    aInt64 = static_cast<int64_t>(u64);

exit:
    return error;
}

otError SpinelDecoder::ReadUintPacked(unsigned int &aUint)
{
    otError        error = OT_ERROR_NONE;
    spinel_ssize_t parsedLen;
    unsigned int   uint;

    parsedLen = spinel_packed_uint_decode(&mFrame[mIndex], mEnd - mIndex, &uint);
    VerifyOrExit(parsedLen > 0, error = OT_ERROR_PARSE);

    mIndex += parsedLen;
    aUint = uint;

exit:
    return error;
}

// Reads an item of given size and updates the pointer `aPtr`.
otError SpinelDecoder::ReadItem(const uint8_t **aPtr, uint16_t aSize)
{
    otError error = OT_ERROR_NONE;

    VerifyOrExit(mIndex + aSize <= mEnd, error = OT_ERROR_PARSE);

    *aPtr = &mFrame[mIndex];

    mIndex += aSize;

exit:
    return error;
}

otError SpinelDecoder::ReadIp6Address(spinel_ipv6addr_t &aIp6Addr)
{
    otError                  error = OT_ERROR_NONE;
    const spinel_ipv6addr_t *ipv6AddrPtr;

    SuccessOrExit(error = ReadIp6Address(ipv6AddrPtr));
    aIp6Addr = *ipv6AddrPtr;

exit:
    return error;
}

otError SpinelDecoder::ReadIp6Address(otIp6Address &aIp6Addr)
{
    otError             error = OT_ERROR_NONE;
    const otIp6Address *ipv6AddrPtr;

    SuccessOrExit(error = ReadIp6Address(ipv6AddrPtr));
    aIp6Addr = *ipv6AddrPtr;

exit:
    return error;
}

otError SpinelDecoder::ReadEui64(spinel_eui64_t &aEui64)
{
    otError               error = OT_ERROR_NONE;
    const spinel_eui64_t *eui64Ptr;

    SuccessOrExit(error = ReadEui64(eui64Ptr));
    aEui64 = *eui64Ptr;

exit:
    return error;
}

otError SpinelDecoder::ReadEui64(otExtAddress &aEui64)
{
    otError             error = OT_ERROR_NONE;
    const otExtAddress *eui64Ptr;

    SuccessOrExit(error = ReadEui64(eui64Ptr));
    aEui64 = *eui64Ptr;

exit:
    return error;
}

otError SpinelDecoder::ReadEui48(spinel_eui48_t &aEui48)
{
    otError               error = OT_ERROR_NONE;
    const spinel_eui48_t *eui48Ptr;

    SuccessOrExit(error = ReadEui48(eui48Ptr));
    aEui48 = *eui48Ptr;

exit:
    return error;
}

otError SpinelDecoder::ReadUtf8(const char *&aUtf8)
{
    otError error = OT_ERROR_NONE;
    size_t  len;

    // Ensure there is at least one byte (for null character).
    VerifyOrExit(mIndex + sizeof(uint8_t) <= mEnd, error = OT_ERROR_PARSE);

    len = StringLength(reinterpret_cast<const char *>(&mFrame[mIndex]), mEnd - mIndex);
    VerifyOrExit(len < static_cast<uint16_t>(mEnd - mIndex), error = OT_ERROR_PARSE);

    aUtf8 = reinterpret_cast<const char *>(&mFrame[mIndex]);

    // `sizeof(uint8_t)` is added for the terminating null character.
    mIndex += static_cast<uint16_t>(len + sizeof(uint8_t));

exit:
    return error;
}

otError SpinelDecoder::ReadData(const uint8_t *&aData, uint16_t &aDataLen)
{
    aDataLen = mEnd - mIndex;

    return ReadItem(&aData, aDataLen);
}

otError SpinelDecoder::ReadDataWithLen(const uint8_t *&aData, uint16_t &aDataLen)
{
    otError  error = OT_ERROR_NONE;
    uint16_t len;

    SuccessOrExit(error = ReadUint16(len));
    SuccessOrExit(error = ReadItem(&aData, len));
    aDataLen = len;

exit:
    return error;
}

otError SpinelDecoder::OpenStruct(void)
{
    otError  error = OT_ERROR_NONE;
    uint16_t structLen;

    VerifyOrExit(mNumOpenStructs < kMaxNestedStructs, error = OT_ERROR_INVALID_STATE);

    SuccessOrExit(error = ReadUint16(structLen));
    VerifyOrExit(structLen <= mEnd - mIndex, error = OT_ERROR_PARSE);

    mPrevEnd[mNumOpenStructs] = mEnd;
    mEnd                      = (mIndex + structLen);
    mNumOpenStructs++;

exit:
    return error;
}

otError SpinelDecoder::CloseStruct(void)
{
    otError error = OT_ERROR_NONE;

    VerifyOrExit(mNumOpenStructs > 0, error = OT_ERROR_INVALID_STATE);

    // If there is a saved position and it is contained
    // within the current struct being closed, the saved
    // position is cleared to ensure user cannot go back
    // to middle of an already closed struct.

    if (IsSavedPositionValid() && (mNumOpenStructs == mSavedNumOpenStructs))
    {
        ClearSavedPosition();
    }

    mNumOpenStructs--;
    mIndex = mEnd;
    mEnd   = mPrevEnd[mNumOpenStructs];

exit:
    return error;
}

void SpinelDecoder::SavePosition(void)
{
    mSavedIndex          = mIndex;
    mSavedEnd            = mEnd;
    mSavedNumOpenStructs = mNumOpenStructs;
}

otError SpinelDecoder::ResetToSaved(void)
{
    otError error = OT_ERROR_NONE;

    VerifyOrExit(IsSavedPositionValid(), error = OT_ERROR_INVALID_STATE);

    mIndex          = mSavedIndex;
    mEnd            = mSavedEnd;
    mNumOpenStructs = mSavedNumOpenStructs;

exit:
    return error;
}

} // namespace Ncp
} // namespace ot
