// Copyright 2023 The Dawn Authors
//
// 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
//
//     http://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.

syntax = "proto2";
package fuzzing;


{% for type in by_category["enum"] %}
    enum {{as_cppType(type.name)}} {
        {% for value in type.values %}
            {{ as_cppType(type.name) }}{{as_cppEnum(value.name)}} = {{ value.value }};
        {% endfor %}
    };
{% endfor %}


{% for type in by_category["bitmask"] %}
    enum {{as_cppType(type.name)}} {
        {% for value in type.values %}
            {{ as_cppType(type.name) }}{{as_cppEnum(value.name)}} = {{ value.value }};
        {% endfor %}
    };
{% endfor %}


{% macro lift_string_proto_member(member, count) -%}
    required string {{ as_protobufNameLPM(member.name) }} = {{ count.value }};
    {% set count.value = count.value + 1 %}
{%- endmacro %}

{% macro lift_float_array_proto_member(member, count) -%}
    repeated float {{ as_varName(member.name) }} = {{ count.value }};
    {% set count.value = count.value + 1 %}
{%- endmacro %}


{% macro lift_varlength_proto_member(member, count) -%}
    {% if member.type in by_category["object"] %}
        repeated uint32 {{ as_protobufNameLPM(member.name) }} = {{ count.value }};
        {% set count.value = count.value + 1 %}
    {% elif member.type.name.get() == "object id" %}
        repeated uint32 {{ as_protobufNameLPM(member.name) }} = {{ count.value }};
        {% set count.value = count.value + 1 %}
    {% elif member.type.name.get() == "uint8_t" %}
        // Skip over byte arrays in protobuf, handled by DawnSerializer
    {% else %}
        repeated {{ as_protobufTypeLPM(member) }} {{ as_protobufNameLPM(member.name) }} = {{ count.value }};
        {% set count.value = count.value + 1 %}
    {% endif %}
{%- endmacro %}


{% macro lift_dawn_member_pass_by_value(record, name, member, count) %}
    {% if member.type in by_category["structure"] %}
        required {{ as_protobufTypeLPM(member) }} {{ as_protobufNameLPM(member.name) }} = {{ count.value }};
        {% set count.value = count.value + 1 %}
    {% elif member.type in by_category["bitmask"] %}
        repeated {{ as_protobufTypeLPM(member) }} {{ as_protobufNameLPM(member.name) }} = {{ count.value }};
        {% set count.value = count.value + 1 %}
    {% elif member.type in by_category["enum"] %}
        required {{ as_protobufTypeLPM(member) }} {{ as_protobufNameLPM(member.name) }} = {{ count.value }};
        {% set count.value = count.value + 1 %}
    {% elif member.type in by_category["object"] %}
        required uint32 {{ as_protobufNameLPM(member.name) }} = {{ count.value }};
        {% set count.value = count.value + 1 %}
    {% elif member.type.name.get() == "ObjectId" %}
        required uint32 {{ as_protobufNameLPM(member.name) }} = {{ count.value }};
        {% set count.value = count.value + 1 %}
    {% elif member.type.name.get() == "ObjectHandle" %}
        // Skips object handles while lifting dawn.json to protobuf because
        // ObjectHandles are created and managed in DawnLPMSerializer. Passing
        // arbitrary ObjectHandles from the fuzzer's bytestream isn't the
        // strategy for this fuzzer.
    {% else %}
        required {{ as_protobufTypeLPM(member) }} {{ as_protobufNameLPM(member.name) }} = {{ count.value }};
        {% set count.value = count.value + 1 %}
    {% endif %}
{% endmacro %}

{% macro lift_dawn_member_pass_by_pointer(record, name, member, count) %}
    {% if member.type in by_category["structure"] and member.length == "constant" and member.constant_length == 1 %}
        required {{ as_protobufTypeLPM(member) }} {{ as_protobufNameLPM(member.name) }} = {{ count.value }};
        {% set count.value = count.value + 1 %}
    {% elif member.type.name.get() == "char" and member.length == 'strlen' %}
        {{ lift_string_proto_member(member, count) }}
    {% elif member.type.name.get() == "float" %}
        {{ lift_float_array_proto_member(member, count) }}
    {% elif member.type.name.get() == "uint8_t" %}
        // Skip over byte arrays in protobuf, handled by DawnLPMSerializer
        // with a hardcoded bytes and length.
    {% elif member.length != 'constant' %}
        {{ lift_varlength_proto_member(member, count) }}
    {% else %}
        // There shouldn't be any other pass-by-pointer types in
        // dawn*.json, if any are added we would like to know at compile time
        {{ unreachable_code }}
    {% endif %}
{% endmacro %}

{% macro lift_proto_members_helper(record, name, members) %}
    {% set count = namespace(value=1) %}
    {% for member in members %}
        {% if member.skip_serialize == True %}
            //  {{ member.name.camelCase()}}.skip_serialize
        {% elif member.annotation == 'value' %}
            {{ lift_dawn_member_pass_by_value(record, name, member, count) }}
        {% elif member.annotation == 'const*' %}
            {{ lift_dawn_member_pass_by_pointer(record, name, member, count) }}
        {% endif %}
    {% endfor %}
{% endmacro %}


{% for structure in by_category["structure"] %}
    message {{structure.name.CamelCase()}} {
        {{ lift_proto_members_helper(structure, structure.name, structure.members) }}
    }
{% endfor %}


{% for command in cmd_records["proto_all_commands"] %}
    {% if command not in cmd_records["proto_generated_commands"] %}
        message {{command.name.CamelCase()}} {}
    {% else %}
        message {{command.name.CamelCase()}} {
            {{ lift_proto_members_helper(command, command.name, command.members) }}
        }
    {% endif %}
{% endfor %}


message Command {
    oneof command {
        {% for command in cmd_records["proto_all_commands"] %}
            {{command.name.CamelCase()}} {{command.name.camelCase()}} = {{ loop.index }};
        {% endfor %}
    }
}

message Program {
    repeated Command commands = 1;
}
