// This file is generated by ValueConversions_h.template.

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

#ifndef {{"_".join(config.protocol.namespace)}}_ValueConversions_h
#define {{"_".join(config.protocol.namespace)}}_ValueConversions_h

//#include "ErrorSupport.h"
//#include "Forward.h"
//#include "Values.h"

{% for namespace in config.protocol.namespace %}
namespace {{namespace}} {
{% endfor %}

template<typename T>
struct ValueConversions {
    static std::unique_ptr<T> fromValue(protocol::Value* value, ErrorSupport* errors)
    {
        return T::fromValue(value, errors);
    }

    static std::unique_ptr<protocol::Value> toValue(T* value)
    {
        return value->toValue();
    }

    static std::unique_ptr<protocol::Value> toValue(const std::unique_ptr<T>& value)
    {
        return value->toValue();
    }
};

template<>
struct ValueConversions<bool> {
    static bool fromValue(protocol::Value* value, ErrorSupport* errors)
    {
        bool result = false;
        bool success = value ? value->asBoolean(&result) : false;
        if (!success)
            errors->addError("boolean value expected");
        return result;
    }

    static std::unique_ptr<protocol::Value> toValue(bool value)
    {
        return FundamentalValue::create(value);
    }
};

template<>
struct ValueConversions<int> {
    static int fromValue(protocol::Value* value, ErrorSupport* errors)
    {
        int result = 0;
        bool success = value ? value->asInteger(&result) : false;
        if (!success)
            errors->addError("integer value expected");
        return result;
    }

    static std::unique_ptr<protocol::Value> toValue(int value)
    {
        return FundamentalValue::create(value);
    }
};

template<>
struct ValueConversions<double> {
    static double fromValue(protocol::Value* value, ErrorSupport* errors)
    {
        double result = 0;
        bool success = value ? value->asDouble(&result) : false;
        if (!success)
            errors->addError("double value expected");
        return result;
    }

    static std::unique_ptr<protocol::Value> toValue(double value)
    {
        return FundamentalValue::create(value);
    }
};

template<>
struct ValueConversions<String> {
    static String fromValue(protocol::Value* value, ErrorSupport* errors)
    {
        String result;
        bool success = value ? value->asString(&result) : false;
        if (!success)
            errors->addError("string value expected");
        return result;
    }

    static std::unique_ptr<protocol::Value> toValue(const String& value)
    {
        return StringValue::create(value);
    }
};

template<>
struct ValueConversions<Binary> {
    static Binary fromValue(protocol::Value* value, ErrorSupport* errors)
    {
        if (!value ||
            (value->type() != Value::TypeBinary && value->type() != Value::TypeString)) {
            errors->addError("Either string base64 or binary value expected");
            return Binary();
        }
        Binary binary;
        if (value->asBinary(&binary))
            return binary;
        String result;
        value->asString(&result);
        bool success;
        Binary out = Binary::fromBase64(result, &success);
        if (!success)
          errors->addError("base64 decoding error");
        return out;
    }

    static std::unique_ptr<protocol::Value> toValue(const Binary& value)
    {
        return BinaryValue::create(value);
    }
};

template<typename T>
struct ValueConversions<std::vector<std::unique_ptr<T>>> {
    static std::unique_ptr<std::vector<std::unique_ptr<T>>> fromValue(protocol::Value* value, ErrorSupport* errors) {
        protocol::ListValue* array = ListValue::cast(value);
        if (!array) {
            errors->addError("array expected");
            return nullptr;
        }
        errors->push();
        std::unique_ptr<std::vector<std::unique_ptr<T>>> result(
            new std::vector<std::unique_ptr<T>>());
        result->reserve(array->size());
        for (size_t i = 0; i < array->size(); ++i) {
            errors->setName(StringUtil::fromInteger(i));
            auto item = ValueConversions<T>::fromValue(array->at(i), errors);
            result->emplace_back(std::move(item));
        }
        errors->pop();
        if (errors->hasErrors())
            return nullptr;
        return result;
    }

    static std::unique_ptr<protocol::ListValue> toValue(std::vector<std::unique_ptr<T>>* v)
    {
        std::unique_ptr<protocol::ListValue> result = ListValue::create();
        result->reserve(v->size());
        for (auto& item : *v)
            result->pushValue(ValueConversions<T>::toValue(item.get()));
        return result;
    }

};

template<typename T>
struct ValueConversions<std::vector<T>> {
    static std::unique_ptr<std::vector<T>> fromValue(protocol::Value* value, ErrorSupport* errors) {
        protocol::ListValue* array = ListValue::cast(value);
        if (!array) {
            errors->addError("array expected");
            return nullptr;
        }
        errors->push();
        std::unique_ptr<std::vector<T>> result(new std::vector<T>());
        result->reserve(array->size());
        for (size_t i = 0; i < array->size(); ++i) {
            errors->setName(StringUtil::fromInteger(i));
            auto item = ValueConversions<T>::fromValue(array->at(i), errors);
            result->emplace_back(std::move(item));
        }
        errors->pop();
        if (errors->hasErrors())
            return nullptr;
        return result;
    }

    static std::unique_ptr<protocol::ListValue> toValue(std::vector<T>* v)
    {
        std::unique_ptr<protocol::ListValue> result = ListValue::create();
        result->reserve(v->size());
        for (auto& item : *v)
            result->pushValue(ValueConversions<T>::toValue(item));
        return result;
    }
};

template<>
struct ValueConversions<Value> {
    static std::unique_ptr<Value> fromValue(protocol::Value* value, ErrorSupport* errors)
    {
        bool success = !!value;
        if (!success) {
            errors->addError("value expected");
            return nullptr;
        }
        return value->clone();
    }

    static std::unique_ptr<protocol::Value> toValue(Value* value)
    {
        return value->clone();
    }

    static std::unique_ptr<protocol::Value> toValue(const std::unique_ptr<Value>& value)
    {
        return value->clone();
    }
};

template<>
struct ValueConversions<DictionaryValue> {
    static std::unique_ptr<DictionaryValue> fromValue(protocol::Value* value, ErrorSupport* errors)
    {
        bool success = value && value->type() == protocol::Value::TypeObject;
        if (!success)
            errors->addError("object expected");
        return DictionaryValue::cast(value->clone());
    }

    static std::unique_ptr<protocol::Value> toValue(DictionaryValue* value)
    {
        return value->clone();
    }

    static std::unique_ptr<protocol::Value> toValue(const std::unique_ptr<DictionaryValue>& value)
    {
        return value->clone();
    }
};

template<>
struct ValueConversions<ListValue> {
    static std::unique_ptr<ListValue> fromValue(protocol::Value* value, ErrorSupport* errors)
    {
        bool success = value && value->type() == protocol::Value::TypeArray;
        if (!success)
            errors->addError("list expected");
        return ListValue::cast(value->clone());
    }

    static std::unique_ptr<protocol::Value> toValue(ListValue* value)
    {
        return value->clone();
    }

    static std::unique_ptr<protocol::Value> toValue(const std::unique_ptr<ListValue>& value)
    {
        return value->clone();
    }
};

{% for namespace in config.protocol.namespace %}
} // namespace {{namespace}}
{% endfor %}

#endif // !defined({{"_".join(config.protocol.namespace)}}_ValueConversions_h)
