// Copyright 2023 The Dawn & Tint Authors
//
// 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.

#include "dawn/fuzzers/lpmfuzz/DawnLPMConstants_autogen.h"
#include "dawn/fuzzers/lpmfuzz/DawnLPMFuzzer.h"
#include "dawn/fuzzers/lpmfuzz/DawnLPMObjectStore.h"
#include "dawn/fuzzers/lpmfuzz/DawnLPMSerializer_autogen.h"
#include "dawn/fuzzers/lpmfuzz/DawnLPMSerializerCustom.h"
#include "dawn/webgpu.h"
#include "dawn/wire/BufferConsumer_impl.h"
#include "dawn/wire/ObjectHandle.h"
#include "dawn/wire/Wire.h"
#include "dawn/wire/WireClient.h"
#include "dawn/wire/WireCmd_autogen.h"
#include "dawn/wire/WireResult.h"
#include "dawn/wire/client/ApiObjects_autogen.h"

namespace dawn::wire {

//* Outputs an rvalue that's the number of elements a pointer member points to.
{% macro member_length(member, proto_accessor) -%}
    {%- if member.length == "constant" -%}
        {{member.constant_length}}u
    {%- else -%}
        {{proto_accessor}}().size()
    {%- endif -%}
{%- endmacro %}

//* Outputs the type that will be used on the wire for the member
{% macro member_type(member) -%}
    {{ assert(as_cType(member.type.name) != "size_t") }}
    {{as_cType(member.type.name)}}
{%- endmacro %}

//* Outputs the conversion code to put `in` in `out`
{% macro convert_member(member, in, out, in_access="") %}
    {% if member.type in by_category["structure"] %}
        {{ convert_structure(member, in, out, in_access) }}
    {% elif member.type in by_category["bitmask"] %}
        {{ convert_bitmask(member, in, out, in_access) }}
    {% elif member.type in by_category["enum"] %}
        {{ convert_enum(member, in, out, in_access) }}
    {% elif member.type in by_category["object"] %}
        {{ convert_object(member, in, out, in_access) }}
    {% elif member.type.name.get() == "ObjectId" %}
        {{ convert_objectid(member, in, out, access) }}
    {% elif member.type.name.get() == "ObjectHandle" %}
        //* Only convert the handle if it maps to an object. Otherwise don't serialize it at all.
        {% if member.handle_type %}
            {{ convert_objecthandle(member, in, out, in_access) }}
        {% endif %}
    {% else %}
        {{out}} = {{in}}({{in_access}});
    {% endif %}
{% endmacro %}

//* Helper functions for converting protobufs to specific types
{% macro convert_enum(member, in, out, in_access) %}
    {{out}} = static_cast<{{ member_type(member) }}>(
                {{in}}({{in_access}})
    );
{% endmacro %}

{% macro convert_object(member, in, out, in_access) -%}
    {{ out }} = reinterpret_cast<{{ as_cType(member.type.name)  }}>(
        objectStores[ObjectType::{{ member.type.name.CamelCase() }}].Lookup(
            static_cast<ObjectId>(
                {{in}}({{in_access}})
            )
        )
    );
{%- endmacro %}

{% macro convert_objectid(member, in, out, in_access) -%}
    {{ out }} = objectStores[ObjectType::{{ member.id_type.name.CamelCase() }}].Lookup(
        static_cast<ObjectId>(
            {{in}}({{ in_access}})
        )
    );
{%- endmacro %}

{% macro convert_objecthandle(member, in, out, in_access) -%}
    if (objectStores[ObjectType::{{ member.handle_type.name.CamelCase() }}].Size() < DawnLPMFuzzer::k{{ member.handle_type.name.CamelCase() }}Limit) {
        {{ out }} = objectStores[ObjectType::{{ member.handle_type.name.CamelCase() }}].ReserveHandle();
    } else {
        // Return failure in this case to guide the fuzzer away from generating too many
        // objects of this type
        return WireResult::FatalError;
    }
{%- endmacro %}

{% macro convert_bitmask(member, in, out, in_access) -%}
    {{ out }} = 0;
    for (size_t bm = 0; bm < static_cast<size_t>({{ in }}().size()); bm++) {
        {{ out }} |=
            static_cast<{{ member_type(member) }}>(
                {{ in }}(bm)
            );
    }
{%- endmacro %}

{% macro convert_structure(member, in, out, in_access) -%}
    // Serializing a Structure Recursively
    WIRE_TRY({{member_type(member)}}ProtoConvert({{in}}({{in_access}}), &{{out}}, serializeBuffer, objectStores));
{%- endmacro %}

{% macro write_record_conversion_helpers(record, name, members, is_cmd) %}
    {% set overrides = cmd_records["lpm_info"]["overrides"]  %}
    {% set overrides_key = record.name.canonical_case()  %}
    {% set name = record.name.CamelCase() %}
    {% set Cmd = "Cmd" if is_cmd else "" %}
    {% set WGPU = "WGPU" if not is_cmd else "" %}

    WireResult {{WGPU}}{{name}}ProtoConvert(fuzzing::{{ name }} proto_record, {{WGPU}}{{ name }}{{ Cmd }} const *record, SerializeBuffer* serializeBuffer, PerObjectType<DawnLPMObjectStore> &objectStores) {

        //* maybe_unused because some commands don't set any members.
        [[maybe_unused]] {{WGPU}}{{ name }}{{ Cmd }} *mutable_record = const_cast<{{WGPU}}{{ name }}{{ Cmd }} *>(record);

        //* Clear the entire structure to make optional handling simpler.
        memset(mutable_record, 0, sizeof({{WGPU}}{{ name }}{{ Cmd }}));

        //* Pass by Value handling. This mirrors WireCmd with some differences between
        //* convert_member and serialize_member
        {% for member in members if member.annotation == "value" if not member.skip_serialize %}
            {% set memberName = as_varName(member.name) %}
            {% set protoMember = as_protobufMemberName(member.name) %}

            {% if member.optional %}
                if ( proto_record.has_{{ protoMember }}() ) {
            {% else %}
                {
            {% endif %}
                //* Major WireCmd Divergence: Some member values are hardcoded in dawn_lpm.json
                {% if overrides_key in overrides and
                   member.name.canonical_case() in overrides[overrides_key] %}
                    mutable_record->{{ memberName }} =
                        {{- overrides[overrides_key][member.name.canonical_case()] }};
                {%- elif member.type.category == "function pointer" or
                    member.type.name.get() == "void *" -%}
                    mutable_record->{{ memberName }} = nullptr;
                {% else %}
                    {{ convert_member(member, 'proto_record.' + protoMember, "mutable_record->" + memberName) }}
                {% endif %}
                }
        {% endfor %}

        //* Chained structures are currently not supported.
        {% if record.extensible %}
            mutable_record->nextInChain = nullptr;
        {% endif %}

        //* TODO(1374747): Create a string type that can be either
        //* random bytes or the fixed entrypoint name.
        {% for member in members if member.length == "strlen" %}
            {% set memberName = as_varName(member.name) %}
            {
                mutable_record->{{ memberName }} = "main";
            }
        {% endfor %}

        //* Pass by Pointer handling. This mirrors WireCmd with some divergences when handling
        //* byte arrays.
        {% for member in members if member.annotation != "value" and member.length != "strlen" and not member.skip_serialize %}
            {% set memberName = as_varName(member.name) %}
            {% set protoMember = as_protobufMemberName(member.name) %}
            {% set protoAccess = "i" if member.length != "constant" or member.constant_length > 1 else "" %}

            //* Major WireCmd Divergence: DawnLPM handles raw byte arrays uniquely
            //* as they don't lead to new coverage, lead to OOMs when allocated with
            //* an arbitrary size, and are difficult to work with in protobuf.
            {% if member.type.name.get() == 'uint8_t' %}
                {
                const size_t kDataBufferLength = 128;
                auto memberLength = kDataBufferLength;

                {{member_type(member)}}* memberBuffer;
                WIRE_TRY(serializeBuffer->NextN(memberLength, &memberBuffer));
                memset(memberBuffer, 0, kDataBufferLength);
                mutable_record->{{ memberName }} = memberBuffer;

                {% if member.length != "constant" -%}
                    mutable_record->{{ member.length.name.camelCase() }} = memberLength;
                {%- endif %}
                }
            {% else %}
                {% set is_fixed_array = true if (member.length == "constant" and member.constant_length > 1) else false %}

                {% if member.optional and not is_fixed_array %}
                    if ( proto_record.has_{{ protoMember }}() ) {
                {% else %}
                    {
                {% endif %}
                    auto memberLength = static_cast<unsigned int>({{member_length(member, "proto_record." + protoMember)}});

                    //* Needed for the edge cases in "external texture descriptor"
                    //* where we want to fuzzer to fill the fixed-length float arrays
                    //* with values, but the length of the protobuf buffer might not
                    //* be large enough for "src transfer function parameters".
                    {% if is_fixed_array %}
                        memberLength = std::min(memberLength,  static_cast<unsigned int>({{"proto_record." + protoMember}}().size()));
                    {% endif %}

                    {{member_type(member)}}* memberBuffer;
                    WIRE_TRY(serializeBuffer->NextN(memberLength, &memberBuffer));

                    for (decltype(memberLength) i = 0; i < memberLength; ++i) {
                        {{convert_member(member, "proto_record." + protoMember, "memberBuffer[i]", protoAccess )}}
                    }

                    mutable_record->{{ memberName }} = memberBuffer;

                    //* Major WireCmd Divergence: Within the serializer the length member is
                    //* set by using record.length. Here we aren't receiving any data
                    //* and set it to the number of protobuf objects in proto_record.
                    {% if member.length != "constant" -%}
                        mutable_record->{{ member.length.name.camelCase() }} = memberLength;
                    {%- endif %}
                    }
            {% endif %}
        {% endfor %}

        return WireResult::Success;
    }
{% endmacro %}

//* Output structure conversion first because it is used by commands.
{% for type in by_category["structure"] %}
    {% set name = as_cType(type.name) %}
    {% if type.name.CamelCase() not in client_side_structures %}
        {{ write_record_conversion_helpers(type, name, type.members, False) }}
    {% endif %}
{% endfor %}

//* Output command conversion functions.
{% for command in cmd_records["cpp_generated_commands"] %}
    {% set name = command.name.CamelCase() %}
    {{ write_record_conversion_helpers(command, name, command.members, True) }}
{% endfor %}

WireResult SerializedData(const fuzzing::Program& program, dawn::wire::ChunkedCommandSerializer serializer) {
    DawnLPMObjectIdProvider provider;
    PerObjectType<DawnLPMObjectStore> objectStores;

    // Allocate a scoped buffer allocation
    const size_t kMaxSerializeBufferSize = 65536;
    std::unique_ptr<char[]> allocatedBuffer(
        new char[kMaxSerializeBufferSize]()
    );

    for (const fuzzing::Command& command : program.commands()) {
        switch (command.command_case()) {

            {% for command in cmd_records["cpp_generated_commands"] %}
            {% set name = command.name.CamelCase() %}
            case fuzzing::Command::k{{name}}: {
                SerializeBuffer serializeBuffer(allocatedBuffer.get(), kMaxSerializeBufferSize);
                {{ name }}Cmd *cmd = nullptr;
                WIRE_TRY(serializeBuffer.Next(&cmd));

                WIRE_TRY({{name}}ProtoConvert(command.{{ command.name.concatcase() }}(), cmd, &serializeBuffer, objectStores));

                serializer.SerializeCommand(*cmd, provider);
                break;
            }
            {% endfor %}
            default: {
                GetCustomSerializedData(command, serializer, objectStores, provider);
                break;
            }
        }
    }

    return WireResult::Success;
}

} // namespace dawn::wire
