/*
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "cppbor_parse.h"

#include <algorithm>
#include <cstdint>
#include <cstring>
#include <memory>
#include <optional>
#include <sstream>
#include <stack>
#include <type_traits>

#include "cppbor.h"

#ifndef __TRUSTY__
#include <android-base/logging.h>
#define LOG_TAG "CppBor"
#else
#define CHECK(x) (void)(x)
#endif

namespace cppbor {

namespace {

const unsigned kMaxParseDepth = 1000;
const size_t kMaxReserveSize = 8192;

std::string insufficientLengthString(size_t bytesNeeded, size_t bytesAvail,
                                     const std::string& type) {
    char buf[1024];
    snprintf(buf, sizeof(buf), "Need %zu byte(s) for %s, have %zu.", bytesNeeded, type.c_str(),
             bytesAvail);
    return std::string(buf);
}

template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>>
std::tuple<bool, uint64_t, const uint8_t*> parseLength(const uint8_t* pos, const uint8_t* end,
                                                       ParseClient* parseClient) {
    if (pos + sizeof(T) > end) {
        parseClient->error(pos - 1, insufficientLengthString(sizeof(T), end - pos, "length field"));
        return {false, 0, pos};
    }

    const uint8_t* intEnd = pos + sizeof(T);
    T result = 0;
    do {
        result = static_cast<T>((result << 8) | *pos++);
    } while (pos < intEnd);
    return {true, result, pos};
}

std::tuple<const uint8_t*, ParseClient*> parseRecursively(const uint8_t* begin, const uint8_t* end,
                                                          bool emitViews, ParseClient* parseClient,
                                                          unsigned depth);

std::tuple<const uint8_t*, ParseClient*> handleUint(uint64_t value, const uint8_t* hdrBegin,
                                                    const uint8_t* hdrEnd,
                                                    ParseClient* parseClient) {
    std::unique_ptr<Item> item = std::make_unique<Uint>(value);
    return {hdrEnd,
            parseClient->item(item, hdrBegin, hdrEnd /* valueBegin */, hdrEnd /* itemEnd */)};
}

std::tuple<const uint8_t*, ParseClient*> handleNint(uint64_t value, const uint8_t* hdrBegin,
                                                    const uint8_t* hdrEnd,
                                                    ParseClient* parseClient) {
    if (value > std::numeric_limits<int64_t>::max()) {
        parseClient->error(hdrBegin, "NINT values that don't fit in int64_t are not supported.");
        return {hdrBegin, nullptr /* end parsing */};
    }
    std::unique_ptr<Item> item = std::make_unique<Nint>(-1 - static_cast<int64_t>(value));
    return {hdrEnd,
            parseClient->item(item, hdrBegin, hdrEnd /* valueBegin */, hdrEnd /* itemEnd */)};
}

std::tuple<const uint8_t*, ParseClient*> handleBool(uint64_t value, const uint8_t* hdrBegin,
                                                    const uint8_t* hdrEnd,
                                                    ParseClient* parseClient) {
    std::unique_ptr<Item> item = std::make_unique<Bool>(value == TRUE);
    return {hdrEnd,
            parseClient->item(item, hdrBegin, hdrEnd /* valueBegin */, hdrEnd /* itemEnd */)};
}

std::tuple<const uint8_t*, ParseClient*> handleNull(const uint8_t* hdrBegin, const uint8_t* hdrEnd,
                                                    ParseClient* parseClient) {
    std::unique_ptr<Item> item = std::make_unique<Null>();
    return {hdrEnd,
            parseClient->item(item, hdrBegin, hdrEnd /* valueBegin */, hdrEnd /* itemEnd */)};
}

#if defined(__STDC_IEC_559__) || FLT_MANT_DIG == 24 || __FLT_MANT_DIG__ == 24
std::tuple<const uint8_t*, ParseClient*> handleFloat(uint32_t value, const uint8_t* hdrBegin,
                                                     const uint8_t* hdrEnd,
                                                     ParseClient* parseClient) {
    float f;
    std::memcpy(&f, &value, sizeof(float));
    std::unique_ptr<Item> item = std::make_unique<Float>(f);
    return {hdrEnd,
            parseClient->item(item, hdrBegin, hdrEnd /* valueBegin */, hdrEnd /* itemEnd */)};
}
#endif  // __STDC_IEC_559__ || FLT_MANT_DIG == 24 || __FLT_MANT_DIG__ == 24

#if defined(__STDC_IEC_559__) || DBL_MANT_DIG == 53 || __DBL_MANT_DIG__ == 53
std::tuple<const uint8_t*, ParseClient*> handleDouble(uint64_t value, const uint8_t* hdrBegin,
                                                      const uint8_t* hdrEnd,
                                                      ParseClient* parseClient) {
    double d;
    std::memcpy(&d, &value, sizeof(double));
    std::unique_ptr<Item> item = std::make_unique<Double>(d);
    return {hdrEnd,
            parseClient->item(item, hdrBegin, hdrEnd /* valueBegin */, hdrEnd /* itemEnd */)};
}
#endif  // __STDC_IEC_559__ || DBL_MANT_DIG == 53 || __DBL_MANT_DIG__ == 53

template <typename T>
std::tuple<const uint8_t*, ParseClient*> handleString(uint64_t length, const uint8_t* hdrBegin,
                                                      const uint8_t* valueBegin, const uint8_t* end,
                                                      const std::string& errLabel,
                                                      ParseClient* parseClient) {
    ssize_t signed_length = static_cast<ssize_t>(length);
    if (end - valueBegin < signed_length || signed_length < 0) {
        parseClient->error(hdrBegin, insufficientLengthString(length, end - valueBegin, errLabel));
        return {hdrBegin, nullptr /* end parsing */};
    }

    std::unique_ptr<Item> item = std::make_unique<T>(valueBegin, valueBegin + length);
    return {valueBegin + length,
            parseClient->item(item, hdrBegin, valueBegin, valueBegin + length)};
}

std::tuple<const uint8_t*, ParseClient*> handleIncompleteString(
        std::unique_ptr<Item> item, const uint8_t* hdrBegin, const uint8_t* valueBegin,
        const uint8_t* end, const std::string& errLabel, bool emitViews, ParseClient* parseClient,
        unsigned depth) {
    parseClient =
            parseClient->item(item, hdrBegin, valueBegin, valueBegin /* don't know the end yet */);
    if (!parseClient) return {hdrBegin, nullptr};

    const uint8_t* pos = valueBegin;
    while (true) {
        if (pos == end) {
            parseClient->error(hdrBegin, "Not enough entries for " + errLabel + ".");
            return {hdrBegin, nullptr /* end parsing */};
        }
        if (*pos == 0xFF) {
            // We found a stop code.
            ++pos;
            break;
        }
        std::tie(pos, parseClient) = parseRecursively(pos, end, emitViews, parseClient, depth + 1);
        if (!parseClient) return {hdrBegin, nullptr};
    }
    if (!parseClient) return {hdrBegin, nullptr};

    return {pos, parseClient->itemEnd(item, hdrBegin, valueBegin, pos)};
}

class IncompleteItem {
  public:
    static IncompleteItem* cast(Item* item);

    virtual ~IncompleteItem() {}
    virtual void add(std::unique_ptr<Item> item) = 0;
    virtual std::unique_ptr<Item> finalize() && = 0;
};

class IncompleteBstr : public Bstr, public IncompleteItem {
  public:
    explicit IncompleteBstr() {}

    // The finalized version creates a copy which will not have this overridden.
    bool isCompound() const override { return true; }

    void add(std::unique_ptr<Item> item) override {
        if (item->type() == BSTR) {
            mValue.insert(mValue.end(), item->asBstr()->moveValue().begin(),
                          item->asBstr()->moveValue().end());
        } else {
#ifndef __TRUSTY__
            LOG(FATAL) << "Should not happen: Expected BSTR";
#endif  // __TRUSTY__
        }
    }

    std::unique_ptr<Item> finalize() && override { return std::make_unique<Bstr>(mValue); }
};

class IncompleteTstr : public Tstr, public IncompleteItem {
  public:
    explicit IncompleteTstr() {}

    // The finalized version creates a copy which will not have this overridden.
    bool isCompound() const override { return true; }

    void add(std::unique_ptr<Item> item) override {
        if (item->type() == TSTR) {
            ss << item->asTstr()->moveValue();
        } else {
#ifndef __TRUSTY__
            LOG(FATAL) << "Should not happen: Expected TSTR";
#endif  // __TRUSTY__
        }
    }

    std::unique_ptr<Item> finalize() && override { return std::make_unique<Tstr>(ss.str()); }

  private:
    std::stringstream ss;
};

class IncompleteArray : public Array, public IncompleteItem {
  public:
    explicit IncompleteArray(std::optional<size_t> size) : mSize(size) {}

    // If the "complete" size is known, return it, otherwise return the current size.
    size_t size() const override { return mSize.value_or(Array::size()); }

    void add(std::unique_ptr<Item> item) override {
        if (mSize) mEntries.reserve(std::min(mSize.value(), kMaxReserveSize));
        mEntries.push_back(std::move(item));
    }

    virtual std::unique_ptr<Item> finalize() && override {
        // Use Array explicitly so the compiler picks the correct ctor overload
        Array* thisArray = this;
        return std::make_unique<Array>(std::move(*thisArray));
    }

  private:
    std::optional<size_t> mSize;
};

class IncompleteMap : public Map, public IncompleteItem {
  public:
    explicit IncompleteMap(std::optional<size_t> size) : mSize(size) {}

    // If the "complete" size is known, return it, otherwise return the current size.
    size_t size() const override { return mSize.value_or(Map::size()); }

    void add(std::unique_ptr<Item> item) override {
        if (mKeyHeldForAdding) {
            if (mSize) mEntries.reserve(std::min(mSize.value(), kMaxReserveSize));
            mEntries.push_back({std::move(mKeyHeldForAdding), std::move(item)});
        } else {
            mKeyHeldForAdding = std::move(item);
        }
    }

    virtual std::unique_ptr<Item> finalize() && override {
        return std::make_unique<Map>(std::move(*this));
    }

  private:
    std::unique_ptr<Item> mKeyHeldForAdding;
    std::optional<size_t> mSize;
};

class IncompleteSemanticTag : public SemanticTag, public IncompleteItem {
  public:
    explicit IncompleteSemanticTag(uint64_t value) : SemanticTag(value) {}

    // We return the "complete" size, rather than the actual size.
    size_t size() const override { return 1; }

    void add(std::unique_ptr<Item> item) override { mTaggedItem = std::move(item); }

    virtual std::unique_ptr<Item> finalize() && override {
        return std::make_unique<SemanticTag>(std::move(*this));
    }
};

IncompleteItem* IncompleteItem::cast(Item* item) {
    CHECK(item->isCompound());
    // Semantic tag must be check first, because SemanticTag::type returns the wrapped item's type.
    if (item->asSemanticTag()) {
#if __has_feature(cxx_rtti)
        CHECK(dynamic_cast<IncompleteSemanticTag*>(item));
#endif
        return static_cast<IncompleteSemanticTag*>(item);
    } else if (item->type() == ARRAY) {
#if __has_feature(cxx_rtti)
        CHECK(dynamic_cast<IncompleteArray*>(item));
#endif
        return static_cast<IncompleteArray*>(item);
    } else if (item->type() == MAP) {
#if __has_feature(cxx_rtti)
        CHECK(dynamic_cast<IncompleteMap*>(item));
#endif
        return static_cast<IncompleteMap*>(item);
    } else if (item->type() == BSTR) {
#if __has_feature(cxx_rtti)
        CHECK(dynamic_cast<IncompleteBstr*>(item));
#endif
        return static_cast<IncompleteBstr*>(item);
    } else if (item->type() == TSTR) {
#if __has_feature(cxx_rtti)
        CHECK(dynamic_cast<IncompleteTstr*>(item));
#endif
        return static_cast<IncompleteTstr*>(item);
    } else {
        CHECK(false);  // Impossible to get here.
    }
    return nullptr;
}

std::tuple<const uint8_t*, ParseClient*> handleEntries(std::optional<size_t> entryCount,
                                                       const uint8_t* hdrBegin, const uint8_t* pos,
                                                       const uint8_t* end,
                                                       const std::string& typeName, bool emitViews,
                                                       ParseClient* parseClient, unsigned depth) {
    while (entryCount.value_or(1) > 0) {
        if (entryCount.has_value()) {
            --*entryCount;
        }
        if (pos == end) {
            parseClient->error(hdrBegin, "Not enough entries for " + typeName + ".");
            return {hdrBegin, nullptr /* end parsing */};
        }
        if (!entryCount.has_value() && *pos == 0xFF) {
            // We're in an indeterminate-length object and found a stop code.
            ++pos;
            break;
        }
        std::tie(pos, parseClient) = parseRecursively(pos, end, emitViews, parseClient, depth + 1);
        if (!parseClient) return {hdrBegin, nullptr};
    }
    return {pos, parseClient};
}

std::tuple<const uint8_t*, ParseClient*> handleCompound(
        std::unique_ptr<Item> item, std::optional<uint64_t> entryCount, const uint8_t* hdrBegin,
        const uint8_t* valueBegin, const uint8_t* end, const std::string& typeName, bool emitViews,
        ParseClient* parseClient, unsigned depth) {
    parseClient =
            parseClient->item(item, hdrBegin, valueBegin, valueBegin /* don't know the end yet */);
    if (!parseClient) return {hdrBegin, nullptr};

    const uint8_t* pos;
    std::tie(pos, parseClient) = handleEntries(entryCount, hdrBegin, valueBegin, end, typeName,
                                               emitViews, parseClient, depth);
    if (!parseClient) return {hdrBegin, nullptr};

    return {pos, parseClient->itemEnd(item, hdrBegin, valueBegin, pos)};
}

std::tuple<const uint8_t*, ParseClient*> parseRecursively(const uint8_t* begin, const uint8_t* end,
                                                          bool emitViews, ParseClient* parseClient,
                                                          unsigned depth) {
    if (begin == end) {
        parseClient->error(
                begin, "Input buffer is empty. Begin and end cannot point to the same location.");
        return {begin, nullptr};
    }

    // Limit recursion depth to avoid overflowing the stack.
    if (depth > kMaxParseDepth) {
        parseClient->error(begin,
                           "Max depth reached.  Cannot parse CBOR structures with more "
                           "than " +
                                   std::to_string(kMaxParseDepth) + " levels.");
        return {begin, nullptr};
    }

    const uint8_t* pos = begin;

    MajorType type = static_cast<MajorType>(*pos & 0xE0);
    uint8_t tagInt = *pos & 0x1F;
    ++pos;

    bool success = true;
    std::optional<uint64_t> addlData;
    if (tagInt < ONE_BYTE_LENGTH) {
        addlData = tagInt;
    } else if (tagInt > EIGHT_BYTE_LENGTH && tagInt != INDEFINITE_LENGTH) {
        parseClient->error(begin, "Reserved additional information value.");
        return {begin, nullptr};
    } else {
        switch (tagInt) {
            case ONE_BYTE_LENGTH:
                std::tie(success, addlData, pos) = parseLength<uint8_t>(pos, end, parseClient);
                break;

            case TWO_BYTE_LENGTH:
                std::tie(success, addlData, pos) = parseLength<uint16_t>(pos, end, parseClient);
                break;

            case FOUR_BYTE_LENGTH:
                std::tie(success, addlData, pos) = parseLength<uint32_t>(pos, end, parseClient);
                break;

            case EIGHT_BYTE_LENGTH:
                std::tie(success, addlData, pos) = parseLength<uint64_t>(pos, end, parseClient);
                break;

            case INDEFINITE_LENGTH:
                // View only strings are not yet supported due to their disjoint nature.
                if (type != ARRAY && type != MAP && !(type == BSTR && !emitViews) &&
                    !(type == TSTR && !emitViews)) {
                    parseClient->error(begin, "Unsupported indefinite length item.");
                    return {begin, nullptr};
                }
                addlData = std::nullopt;
                break;

            default:
                CHECK(false);  //  It's impossible to get here
                break;
        }
    }

    if (!success) return {begin, nullptr};

    switch (type) {
        case UINT:
            return handleUint(*addlData, begin, pos, parseClient);

        case NINT:
            return handleNint(*addlData, begin, pos, parseClient);

        case BSTR:
            if (!addlData.has_value()) {
                return handleIncompleteString(std::make_unique<IncompleteBstr>(), begin, pos, end,
                                              "byte string", emitViews, parseClient, depth);
            } else if (emitViews) {
                return handleString<ViewBstr>(*addlData, begin, pos, end, "byte string",
                                              parseClient);
            } else {
                return handleString<Bstr>(*addlData, begin, pos, end, "byte string", parseClient);
            }

        case TSTR:
            if (!addlData.has_value()) {
                return handleIncompleteString(std::make_unique<IncompleteTstr>(), begin, pos, end,
                                              "text string", emitViews, parseClient, depth);
            } else if (emitViews) {
                return handleString<ViewTstr>(*addlData, begin, pos, end, "text string",
                                              parseClient);
            } else {
                return handleString<Tstr>(*addlData, begin, pos, end, "text string", parseClient);
            }

        case ARRAY:
            return handleCompound(std::make_unique<IncompleteArray>(addlData), addlData, begin, pos,
                                  end, "array", emitViews, parseClient, depth);

        case MAP:
            return handleCompound(std::make_unique<IncompleteMap>(addlData),
                                  addlData.has_value() ? *addlData * 2 : addlData, begin, pos, end,
                                  "map", emitViews, parseClient, depth);

        case SEMANTIC:
            return handleCompound(std::make_unique<IncompleteSemanticTag>(*addlData), 1, begin, pos,
                                  end, "semantic", emitViews, parseClient, depth);

        case SIMPLE:
            switch (tagInt) {
                case TRUE:
                case FALSE:
                    return handleBool(*addlData, begin, pos, parseClient);
                case FLOAT_V:
#if defined(__STDC_IEC_559__) || FLT_MANT_DIG == 24 || __FLT_MANT_DIG__ == 24
                    return handleFloat(*addlData, begin, pos, parseClient);
#else
                    parseClient->error(begin, "Value float is not supported for platform.");
                    return {begin, nullptr};
#endif  // __STDC_IEC_559__ || FLT_MANT_DIG == 24 || __FLT_MANT_DIG__ == 24
                case DOUBLE_V:
#if defined(__STDC_IEC_559__) || DBL_MANT_DIG == 53 || __DBL_MANT_DIG__ == 53
                    return handleDouble(*addlData, begin, pos, parseClient);
#else
                    parseClient->error(begin, "Value double is not supported for platform.");
                    return {begin, nullptr};
#endif  // __STDC_IEC_559__ || DBL_MANT_DIG == 53 || __DBL_MANT_DIG__ == 53
                case NULL_V:
                    return handleNull(begin, pos, parseClient);
                default:
                    parseClient->error(begin, "Unsupported half-floating-point or simple value.");
                    return {begin, nullptr};
            }
    }
    CHECK(false);  // Impossible to get here.
    return {};
}

class FullParseClient : public ParseClient {
  public:
    virtual ParseClient* item(std::unique_ptr<Item>& item, const uint8_t*, const uint8_t*,
                              const uint8_t* end) override {
        if (mParentStack.empty() && !item->isCompound()) {
            // This is the first and only item.
            mTheItem = std::move(item);
            mPosition = end;
            return nullptr;  //  We're done.
        }

        if (item->isCompound()) {
            // Starting a new compound data item, i.e. a new parent.  Save it on the parent stack.
            // It's safe to save a raw pointer because the unique_ptr is guaranteed to stay in
            // existence until the corresponding itemEnd() call.
            mParentStack.push(item.get());
            return this;
        } else {
            return appendToLastParent(std::move(item));
        }
    }

    virtual ParseClient* itemEnd(std::unique_ptr<Item>& item, const uint8_t*, const uint8_t*,
                                 const uint8_t* end) override {
        CHECK(item->isCompound() && item.get() == mParentStack.top());
        mParentStack.pop();
        IncompleteItem* incompleteItem = IncompleteItem::cast(item.get());
        std::unique_ptr<Item> finalizedItem = std::move(*incompleteItem).finalize();

        if (mParentStack.empty()) {
            mTheItem = std::move(finalizedItem);
            mPosition = end;
            return nullptr;  // We're done
        } else {
            return appendToLastParent(std::move(finalizedItem));
        }
    }

    virtual void error(const uint8_t* position, const std::string& errorMessage) override {
        mPosition = position;
        mErrorMessage = errorMessage;
    }

    std::tuple<std::unique_ptr<Item> /* result */, const uint8_t* /* newPos */,
               std::string /* errMsg */>
    parseResult() {
        std::unique_ptr<Item> p = std::move(mTheItem);
        return {std::move(p), mPosition, std::move(mErrorMessage)};
    }

  private:
    ParseClient* appendToLastParent(std::unique_ptr<Item> item) {
        auto parent = mParentStack.top();
        switch (parent->type()) {
            case BSTR:
                if (item->type() != BSTR) {
                    mErrorMessage += "Expected BSTR in indefinite-length string.";
                    return nullptr;
                }
                IncompleteItem::cast(parent)->add(std::move(item));
                break;
            case TSTR:
                if (item->type() != TSTR) {
                    mErrorMessage += "Expected TSTR in indefinite-length string.";
                    return nullptr;
                }
                IncompleteItem::cast(parent)->add(std::move(item));
                break;
            default:
                IncompleteItem::cast(parent)->add(std::move(item));
                break;
        }
        return this;
    }

    std::unique_ptr<Item> mTheItem;
    std::stack<Item*> mParentStack;
    const uint8_t* mPosition = nullptr;
    std::string mErrorMessage;
};

}  // anonymous namespace

void parse(const uint8_t* begin, const uint8_t* end, ParseClient* parseClient) {
    parseRecursively(begin, end, false, parseClient, 0);
}

std::tuple<std::unique_ptr<Item> /* result */, const uint8_t* /* newPos */,
           std::string /* errMsg */>
parse(const uint8_t* begin, const uint8_t* end) {
    FullParseClient parseClient;
    parse(begin, end, &parseClient);
    return parseClient.parseResult();
}

void parseWithViews(const uint8_t* begin, const uint8_t* end, ParseClient* parseClient) {
    parseRecursively(begin, end, true, parseClient, 0);
}

std::tuple<std::unique_ptr<Item> /* result */, const uint8_t* /* newPos */,
           std::string /* errMsg */>
parseWithViews(const uint8_t* begin, const uint8_t* end) {
    FullParseClient parseClient;
    parseWithViews(begin, end, &parseClient);
    return parseClient.parseResult();
}

}  // namespace cppbor
