/*
 * 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 <sstream>
#include <stack>

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

namespace cppbor {

namespace {

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);

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 */)};
}

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)};
}

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

class IncompleteArray : public Array, public IncompleteItem {
  public:
    explicit IncompleteArray(size_t size) : mSize(size) {}

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

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

  private:
    size_t mSize;
};

class IncompleteMap : public Map, public IncompleteItem {
  public:
    explicit IncompleteMap(size_t size) : mSize(size) {}

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

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

  private:
    std::unique_ptr<Item> mKeyHeldForAdding;
    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); }
};

std::tuple<const uint8_t*, ParseClient*> handleEntries(size_t entryCount, const uint8_t* hdrBegin,
                                                       const uint8_t* pos, const uint8_t* end,
                                                       const std::string& typeName,
                                                       bool emitViews,
                                                       ParseClient* parseClient) {
    while (entryCount > 0) {
        --entryCount;
        if (pos == end) {
            parseClient->error(hdrBegin, "Not enough entries for " + typeName + ".");
            return {hdrBegin, nullptr /* end parsing */};
        }
        std::tie(pos, parseClient) = parseRecursively(pos, end, emitViews, parseClient);
        if (!parseClient) return {hdrBegin, nullptr};
    }
    return {pos, parseClient};
}

std::tuple<const uint8_t*, ParseClient*> handleCompound(
        std::unique_ptr<Item> item, uint64_t entryCount, const uint8_t* hdrBegin,
        const uint8_t* valueBegin, const uint8_t* end, const std::string& typeName,
        bool emitViews, ParseClient* parseClient) {
    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);
    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) {
    if (begin == end) {
        parseClient->error(
                begin,
                "Input buffer is empty. Begin and end cannot point to the same location.");
        return {begin, nullptr};
    }

    const uint8_t* pos = begin;

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

    bool success = true;
    uint64_t addlData;
    if (tagInt < ONE_BYTE_LENGTH) {
        addlData = tagInt;
    } else if (tagInt > EIGHT_BYTE_LENGTH) {
        parseClient->error(
                begin,
                "Reserved additional information value or unsupported indefinite length item.");
        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;

            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 (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 (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);

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

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

        case SIMPLE:
            switch (addlData) {
                case TRUE:
                case FALSE:
                    return handleBool(addlData, begin, pos, parseClient);
                case NULL_V:
                    return handleNull(begin, pos, parseClient);
                default:
                    parseClient->error(begin, "Unsupported 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 {
            appendToLastParent(std::move(item));
            return this;
        }
    }

    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();

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

    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:
    void appendToLastParent(std::unique_ptr<Item> item) {
        auto parent = mParentStack.top();
#if __has_feature(cxx_rtti)
        assert(dynamic_cast<IncompleteItem*>(parent));
#endif

        IncompleteItem* parentItem{};
        if (parent->type() == ARRAY) {
            parentItem = static_cast<IncompleteArray*>(parent);
        } else if (parent->type() == MAP) {
            parentItem = static_cast<IncompleteMap*>(parent);
        } else if (parent->asSemanticTag()) {
            parentItem = static_cast<IncompleteSemanticTag*>(parent);
        } else {
            CHECK(false);  // Impossible to get here.
        }
        parentItem->add(std::move(item));
    }

    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);
}

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);
}

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
