/*
 * Copyright (C) 2013-2017 Apple Inc. 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
 */

#pragma once

#include <functional>
#include <wtf/Deque.h>
#include <wtf/Forward.h>

namespace WebCore {

class SharedBuffer;

class KeyedDecoder {
    WTF_MAKE_FAST_ALLOCATED;
public:
    WEBCORE_EXPORT static std::unique_ptr<KeyedDecoder> decoder(const uint8_t* data, size_t);

    virtual ~KeyedDecoder() = default;

    virtual bool decodeBytes(const String& key, const uint8_t*&, size_t&) = 0;
    virtual bool decodeBool(const String& key, bool&) = 0;
    virtual bool decodeUInt32(const String& key, uint32_t&) = 0;
    virtual bool decodeUInt64(const String& key, uint64_t&) = 0;
    virtual bool decodeInt32(const String& key, int32_t&) = 0;
    virtual bool decodeInt64(const String& key, int64_t&) = 0;
    virtual bool decodeFloat(const String& key, float&) = 0;
    virtual bool decodeDouble(const String& key, double&) = 0;
    virtual bool decodeString(const String& key, String&) = 0;

    template<typename T>
    bool decodeBytes(const String& key, Vector<T>& vector)
    {
        static_assert(sizeof(T) == 1, "");

        size_t size;
        const uint8_t* bytes;
        if (!decodeBytes(key, bytes, size))
            return false;

        vector.resize(size);
        std::copy(bytes, bytes + size, vector.data());
        return true;
    }

    template<typename T, typename F>
    bool decodeEnum(const String& key, T& value, F&& isValidEnumFunction)
    {
        static_assert(std::is_enum<T>::value, "T must be an enum type");

        int64_t intValue;
        if (!decodeInt64(key, intValue))
            return false;

        if (!isValidEnumFunction(static_cast<T>(intValue)))
            return false;

        value = static_cast<T>(intValue);
        return true;
    }

    template<typename T, typename F>
    bool decodeObject(const String& key, T& object, F&& function)
    {
        if (!beginObject(key))
            return false;
        bool result = function(*this, object);
        endObject();
        return result;
    }

    template<typename T, typename F>
    bool decodeConditionalObject(const String& key, T& object, F&& function)
    {
        // FIXME: beginObject can return false for two reasons: either the
        // key doesn't exist or the key refers to something that isn't an object.
        // Because of this, decodeConditionalObject won't distinguish between a
        // missing object or a value that isn't an object.
        if (!beginObject(key))
            return true;

        bool result = function(*this, object);
        endObject();
        return result;
    }

    template<typename ContainerType, typename F>
    bool decodeObjects(const String& key, ContainerType& objects, F&& function)
    {
        if (!beginArray(key))
            return false;

        bool result = true;
        while (beginArrayElement()) {
            typename ContainerType::ValueType element;
            if (!function(*this, element)) {
                result = false;
                endArrayElement();
                break;
            }
            objects.append(WTFMove(element));
            endArrayElement();
        }

        endArray();
        return result;
    }

protected:
    KeyedDecoder()
    {
    }

private:
    virtual bool beginObject(const String& key) = 0;
    virtual void endObject() = 0;

    virtual bool beginArray(const String& key) = 0;
    virtual bool beginArrayElement() = 0;
    virtual void endArrayElement() = 0;
    virtual void endArray() = 0;
};

class KeyedEncoder {
    WTF_MAKE_FAST_ALLOCATED;
public:
    WEBCORE_EXPORT static std::unique_ptr<KeyedEncoder> encoder();

    virtual ~KeyedEncoder() = default;

    virtual void encodeBytes(const String& key, const uint8_t*, size_t) = 0;
    virtual void encodeBool(const String& key, bool) = 0;
    virtual void encodeUInt32(const String& key, uint32_t) = 0;
    virtual void encodeUInt64(const String& key, uint64_t) = 0;
    virtual void encodeInt32(const String& key, int32_t) = 0;
    virtual void encodeInt64(const String& key, int64_t) = 0;
    virtual void encodeFloat(const String& key, float) = 0;
    virtual void encodeDouble(const String& key, double) = 0;
    virtual void encodeString(const String& key, const String&) = 0;

    virtual RefPtr<SharedBuffer> finishEncoding() = 0;

    template<typename T>
    void encodeEnum(const String& key, T value)
    {
        static_assert(std::is_enum<T>::value, "T must be an enum type");

        encodeInt64(key, static_cast<int64_t>(value));
    }

    template<typename T, typename F>
    void encodeObject(const String& key, const T& object, F&& function)
    {
        beginObject(key);
        function(*this, object);
        endObject();
    }

    template<typename T, typename F>
    void encodeConditionalObject(const String& key, const T* object, F&& function)
    {
        if (!object)
            return;

        encodeObject(key, *object, std::forward<F>(function));
    }

    template<typename T, typename F>
    void encodeObjects(const String& key, T begin, T end, F&& function)
    {
        beginArray(key);
        for (T it = begin; it != end; ++it) {
            beginArrayElement();
            function(*this, *it);
            endArrayElement();
        }
        endArray();
    }

protected:
    KeyedEncoder()
    {
    }

private:
    virtual void beginObject(const String& key) = 0;
    virtual void endObject() = 0;

    virtual void beginArray(const String& key) = 0;
    virtual void beginArrayElement() = 0;
    virtual void endArrayElement() = 0;
    virtual void endArray() = 0;
};

} // namespace WebCore
