{% import "mojolpm_macros.tmpl" as util %}
{%- macro declare_array(type, kind) %}
{%- set mojom_type = kind.kind|cpp_wrapper_type(add_same_module_namespaces=true) %}
{%- if kind.kind|is_nullable_kind %}
{%- set maybe_mojom_type = kind.kind|to_unnullable_kind|cpp_wrapper_type(add_same_module_namespaces=true) %}
{%- else %}
{%- set maybe_mojom_type = mojom_type %}
{%- endif %}
bool ToProto(
{%- if kind.kind|is_move_only_kind %}
std::vector<{{mojom_type}}>&& input,
{%- else %}
const std::vector<{{mojom_type}}>& input,
{%- endif %}
{{type}}& output);{{"\n"-}}
{%- if kind.kind|is_array_kind %}
{{declare_array(type ~ "Entry", kind.kind)}}
{%- elif kind.kind|is_map_kind %}
{{declare_map(type ~ "Entry", kind.kind)}}
{%- else %}
bool ToProto(
{{maybe_mojom_type}} input,
{{type}}Entry& output);{{"\n"-}}
{%- endif %}
{%- endmacro %}
{%- macro declare_map(type, kind) %}
{%- set mojom_key_type = kind.key_kind|cpp_wrapper_call_type(add_same_module_namespaces=true) %}
{%- set mojom_value_type = kind.value_kind|cpp_wrapper_call_type(add_same_module_namespaces=true) %}
bool ToProto(
{%- if kind.key_kind|is_move_only_kind or kind.value_kind|is_move_only_kind %}
base::flat_map<{{mojom_key_type}},
{{mojom_value_type}}>&& input,
{%- else %}
const base::flat_map<{{mojom_key_type}},
{{mojom_value_type}}>& input,
{%- endif %}
{{type}}& output);{{"\n"-}}
{%- if kind.key_kind|is_array_kind %}
{{- declare_array(type ~ "Key", kind.key_kind)}}
{%- elif kind.key_kind|is_map_kind %}
{{- declare_map(type ~ "Key", kind.key_kind)}}
{%- else %}
bool ToProto(
{{mojom_key_type}} input,
{{type}}Key& output);{{"\n"-}}
{%- endif %}
{%- if kind.value_kind|is_array_kind %}
{{- declare_array(type ~ "Value", kind.value_kind)}}
{%- elif kind.value_kind|is_map_kind %}
{{- declare_map(type ~ "Value", kind.value_kind)}}
{%- elif kind.value_kind|is_nullable_kind %}
bool ToProto(
{{mojom_value_type}} input,
{{type}}Value& output);{{"\n"-}}
{%- else %}
bool ToProto(
{{mojom_value_type}} input,
{{type}}Value& output);{{"\n"-}}
{%- endif %}
{%- endmacro %}
{%- macro declare(parent_name, kind, name) %}
{%- if kind|is_array_kind %}
{%- set array_type = parent_name ~ "::" ~ name|under_to_camel ~ "_Array" %}
{{- declare_array(array_type, kind)}}
{%- elif kind|is_map_kind %}
{%- set map_type = parent_name ~ "::" ~ name|under_to_camel ~ "_Map" %}
{{- declare_map(map_type, kind)}}
{%- endif %}
{%- endmacro %}
{%- macro define_array(type, kind) %}
{%- set maybe_const = "const " if not kind.kind|is_move_only_kind else "" %}
{%- set mojom_type = kind.kind|cpp_wrapper_type(add_same_module_namespaces=true) %}
{%- if kind.kind|is_nullable_kind %}
{%- set maybe_mojom_type = kind.kind|to_unnullable_kind|cpp_wrapper_type(add_same_module_namespaces=true) %}
{%- else %}
{%- set maybe_mojom_type = mojom_type %}
{%- endif %}
bool ToProto(
{%- if kind.kind|is_move_only_kind %}
std::vector<{{mojom_type}}>&& input,
{%- else %}
const std::vector<{{mojom_type}}>& input,
{%- endif %}
{{type}}& output) {
bool result = true;
for (auto&& in_value : input) {
{%- if kind.kind|is_nullable_kind %}
{{type}}Entry* out_value = output.mutable_values()->Add();
if ({{util.not_null(kind.kind, 'in_value')}}) {
{%- if kind.kind|is_move_only_kind %}
ToProto(std::move({{util.value(kind.kind, 'in_value')}}), *out_value);
{%- else %}
ToProto({{util.value(kind.kind, 'in_value')}}, *out_value);
{%- endif %}
}
{%- else %}
{{type}}Entry* out_value = output.mutable_values()->Add();
{%- if kind.kind|is_move_only_kind %}
ToProto(std::move({{util.value(kind.kind, 'in_value')}}), *out_value);
{%- else %}
ToProto({{util.value(kind.kind, 'in_value')}}, *out_value);
{%- endif %}
{%- endif %}
}
return result;
}{{"\n"-}}
{%- if kind.kind|is_array_kind %}
{{- define_array(type ~ "Entry", kind.kind)}}
{%- elif kind.kind|is_map_kind %}
{{- define_map(type ~ "Entry", kind.kind)}}
{%- elif kind.kind|is_nullable_kind and not kind.kind|is_value_kind %}
bool ToProto(
{{maybe_const}}{{maybe_mojom_type}} input,
{{type}}Entry& output) {
{%- if kind.kind|is_move_only_kind %}
return ToProto(std::move(input), *output.mutable_value());
{%- else %}
return ToProto(input, *output.mutable_value());
{%- endif %}
}{{"\n"-}}
{%- else %}
bool ToProto(
{{maybe_const}}{{mojom_type}} input,
{{type}}Entry& output) {
{%- if kind.kind|is_value_kind %}
bool mojolpm_result = true;
{{kind.kind|cpp_wrapper_proto_type(add_same_module_namespaces=true)}} value;
{%- if kind.kind|is_nullable_kind %}
if (input.has_value()) {
mojolpm_result = ToProto(input.value(), value);
output.set_value(value);
}
{%- else %}
mojolpm_result = ToProto(input, value);
output.set_value(value);
{%- endif %}
return mojolpm_result;
{%- elif kind.kind|is_any_interface_kind %}
bool mojolpm_result;
{{kind.kind|cpp_wrapper_proto_type(add_same_module_namespaces=true)}} value;
mojolpm_result = ToProto(std::move(input), value);
output.set_value(value);
return mojolpm_result;
{%- elif kind.kind|is_move_only_kind %}
return ToProto(std::move(input), *output.mutable_value());
{%- elif kind.kind|is_nullable_kind and not kind.kind|nullable_is_same_kind %}
if (input) {
return ToProto(*input, *output.mutable_value());
} else {
return true;
}
{%- else %}
return ToProto(input, *output.mutable_value());
{%- endif %}
}{{"\n"-}}
{%- endif %}
{%- endmacro %}
{%- macro define_map(type, kind) %}
{%- set maybe_const_key = "const " if not kind.key_kind|is_move_only_kind else "" %}
{%- set mojom_key_type = kind.key_kind|cpp_wrapper_call_type(add_same_module_namespaces=true) %}
{%- set maybe_const_value = "const " if not kind.key_kind|is_move_only_kind else "" %}
{%- set mojom_value_type = kind.value_kind|cpp_wrapper_call_type(add_same_module_namespaces=true) %}
bool ToProto(
{%- if kind.key_kind|is_move_only_kind or kind.value_kind|is_move_only_kind %}
base::flat_map<{{mojom_key_type}},
{{mojom_value_type}}>&& input,
{%- else %}
const base::flat_map<{{mojom_key_type}},
{{mojom_value_type}}>& input,
{%- endif %}
{{type}}& output) {
bool result = true;
for (auto& in_entry : input) {
auto out_entry = output.mutable_values()->Add();
{%- if kind.key_kind|is_move_only_kind %}
result = ToProto(std::move(in_entry.first), *out_entry->mutable_key());
{%- else %}
result = ToProto(in_entry.first, *out_entry->mutable_key());
{%- endif %}
if (!result) {
break;
}
{%- if kind.value_kind|is_nullable_kind %}
if ({{util.not_null(kind.value_kind, 'in_entry.second')}}) {
{%- if kind.value_kind|is_struct_kind %}
result = ToProto(std::move(in_entry.second), *out_entry->mutable_value());
{%- elif kind.value_kind|is_move_only_kind %}
result = ToProto(std::move(*in_entry.second), *out_entry->mutable_value());
{%- else %}
result = ToProto(*in_entry.second, *out_entry->mutable_value());
{%- endif %}
}
{%- elif kind.value_kind|is_move_only_kind %}
result = ToProto(std::move(in_entry.second), *out_entry->mutable_value());
{%- else %}
result = ToProto(in_entry.second, *out_entry->mutable_value());
{%- endif %}
if (!result) {
break;
}
}
return result;
}{{"\n"-}}
{%- if kind.key_kind|is_array_kind %}
{{define_array(type ~ "Key", kind.key_kind)}}
{%- elif kind.key_kind|is_map_kind %}
{{define_map(type ~ "Key", kind.key_kind)}}
{%- else %}
bool ToProto(
{{mojom_key_type}} input,
{{type}}Key& output) {
{%- if kind.key_kind|is_value_kind %}
bool mojolpm_result;
{{kind.key_kind|cpp_wrapper_proto_type(add_same_module_namespaces=true)}} value;
mojolpm_result = ToProto(input, value);
output.set_value(value);
return mojolpm_result;
{%- elif kind.key_kind|is_move_only_kind %}
return ToProto(std::move(input), *output.mutable_value());
{%- elif kind.key_kind|is_nullable_kind and not kind.key_kind|nullable_is_same_kind %}
if (input) {
return ToProto(*input, *output.mutable_value());
} else {
return true;
}
{%- else %}
return ToProto(input, *output.mutable_value());
{%- endif %}
}{{"\n"-}}
{%- endif %}
{%- if kind.value_kind|is_array_kind %}
{{- define_array(type ~ "Value", kind.value_kind)}}
{%- elif kind.value_kind|is_map_kind %}
{{- define_map(type ~ "Value", kind.value_kind)}}
{%- else %}
bool ToProto(
{{mojom_value_type}} input,
{{type}}Value& output) {
{%- if kind.value_kind|is_value_kind %}
bool mojolpm_result = true;
{{kind.value_kind|cpp_wrapper_proto_type(add_same_module_namespaces=true)}} value;
{%- if kind.value_kind|is_nullable_kind %}
if (input.has_value()) {
mojolpm_result = ToProto(input.value(), value);
output.set_value(value);
}
{%- else %}
mojolpm_result = ToProto(input, value);
output.set_value(value);
{%- endif %}
return mojolpm_result;
{%- elif kind.value_kind|is_any_interface_kind %}
bool mojolpm_result;
{{kind.value_kind|cpp_wrapper_proto_type(add_same_module_namespaces=true)}} value;
mojolpm_result = ToProto(std::move(input), value);
output.set_value(value);
return mojolpm_result;
{%- elif kind.value_kind|is_nullable_kind and not kind.value_kind|nullable_is_same_kind %}
if (input) {
{%- if kind.value_kind|is_move_only_kind %}
return ToProto(std::move(*input), *output.mutable_value());
{%- else %}
return ToProto(*input, *output.mutable_value());
{%- endif %}
} else {
return true;
}
{%- elif kind.value_kind|is_move_only_kind %}
return ToProto(std::move(input), *output.mutable_value());
{%- else %}
return ToProto(input, *output.mutable_value());
{%- endif %}
}{{"\n"-}}
{%- endif %}
{%- endmacro %}
{%- macro define(parent_name, kind, name) %}
{%- if kind|is_array_kind %}
{%- set array_type = parent_name ~ "::" ~ name|under_to_camel ~ "_Array" %}
{{- define_array(array_type, kind)}}
{%- elif kind|is_map_kind %}
{%- set map_type = parent_name ~ "::" ~ name|under_to_camel ~ "_Map" %}
{{- define_map(map_type, kind)}}
{%- endif %}
{%- endmacro %}
{%- macro define_enum(enum) -%}
{%- set mojom_type = enum|cpp_wrapper_call_type(add_same_module_namespaces=true) %}
{%- set proto_type = "::mojolpm" ~ (enum|get_qualified_name_for_kind(flatten_nested_kind=True)) %}
{%- set enum_type = enum|get_qualified_name_for_kind(flatten_nested_kind=True) %}
bool ToProto(
const {{mojom_type}}& input,
{{proto_type}}& output) {
{%- if enum|is_native_only_kind or not enum|is_typemapped_kind %}
// This ignores IPC_PARAM_TRAITS for native IPC enums, but internal to the
// fuzzer we don't want the overhead of the serialization layer if we don't
// need it. This doesn't change the actual checks on the receiving end.
output = static_cast<{{proto_type}}>(input);
return true;
{%- else %}
output = static_cast<{{proto_type}}>(
::mojo::EnumTraits<{{enum_type}}, {{mojom_type}}>::ToMojom(input));
return true;
{%- endif %}
}{{"\n"-}}
{%- endmacro %}
{%- macro define_struct(struct) -%}
{%- set mojom_type = struct|cpp_wrapper_param_type(add_same_module_namespaces=true) %}
{%- set proto_type = "::mojolpm" ~ (struct|get_qualified_name_for_kind(flatten_nested_kind=True)) %}
{%- set struct_type = proto_type ~ "_ProtoStruct" %}
bool ToProto(
{{mojom_type}} input,
{{proto_type}}& output) {
{%- if struct|is_native_only_kind %}
{{struct_type}}* new_instance = output.mutable_new_();
std::string* bytes = new_instance->mutable_native_bytes();
bytes->resize(sizeof({{mojom_type}}), 0);
memcpy(bytes->data(), (void*)&input, sizeof({{mojom_type}}));
return true;
{%- elif struct|is_typemapped_kind %}
// TODO(markbrand): ToProto for typemapped struct kind
return false;
{%- elif struct.fields %}
{{struct_type}}* new_instance = output.mutable_new_();
bool mojolpm_result = true;
{%- for field in struct.fields -%}
{%- set raw_name = field.name %}
{%- set name = field.name|camel_to_under %}
{%- set kind = field.kind %}
{%- if kind|is_any_interface_kind %}
{{kind|cpp_wrapper_proto_type(add_same_module_namespaces=true)}} tmp_{{name}};
mojolpm_result &= ToProto(std::move(input->{{raw_name}}), tmp_{{name}});
new_instance->set_m_{{name}}(tmp_{{name}});
{%- elif kind|is_nullable_kind %}
if ({{util.not_null(kind, 'input->' ~ raw_name)}}) {
{%- if kind|is_value_kind %}
{{kind|cpp_wrapper_proto_type(add_same_module_namespaces=true)}} tmp_{{name}};
mojolpm_result &= ToProto(*input->{{raw_name}}, tmp_{{name}});
new_instance->set_m_{{name}}(tmp_{{name}});
{%- elif kind|is_move_only_kind %}
mojolpm_result &= ToProto(std::move({{util.value(kind, 'input->' ~ raw_name)}}), *new_instance->mutable_m_{{name}}());
{%- else %}
mojolpm_result &= ToProto({{util.value(kind, 'input->' ~ raw_name)}}, *new_instance->mutable_m_{{name}}());
{%- endif %}
}
{%- elif kind|is_move_only_kind %}
mojolpm_result &= ToProto(std::move(input->{{raw_name}}), *new_instance->mutable_m_{{name}}());
{%- elif kind|is_value_kind %}
{{kind|cpp_wrapper_proto_type(add_same_module_namespaces=true)}} tmp_{{name}};
mojolpm_result &= ToProto(input->{{raw_name}}, tmp_{{name}});
new_instance->set_m_{{name}}(tmp_{{name}});
{%- else %}
mojolpm_result &= ToProto(input->{{raw_name}}, *new_instance->mutable_m_{{name}}());
{%- endif %}
{%- endfor %}
return mojolpm_result;
{%- else %}
output.new_();
return true;
{%- endif %}
}{{"\n"-}}
{%- endmacro %}
{%- macro define_union(union) %}
{%- set mojom_type = union|cpp_wrapper_param_type(add_same_module_namespaces=true) %}
{%- set proto_type = "::mojolpm" ~ (union|get_qualified_name_for_kind(flatten_nested_kind=True)) %}
{%- set union_type = proto_type ~ "_ProtoUnion" %}
bool ToProto(
{{mojom_type}} input,
{{proto_type}}& output) {
{%- if union|is_typemapped_kind %}
// TODO(markbrand): ToProto for typemapped union kind.
return false;
{%- else %}
{%- set enum_name = (union|get_qualified_name_for_kind(flatten_nested_kind=True, internal=True)) ~ "::" ~ union.name ~ "_Tag" %}
{{union_type}}* new_instance = output.mutable_new_();
bool mojolpm_result = true;
switch (input->which()) {
{%- for field in union.fields %}
{%- set raw_name = field.name %}
{%- set name = field.name|camel_to_under %}
{%- set kind = field.kind %}
case {{enum_name}}::k{{field.name|under_to_camel(digits_split=false)}}: {
{%- if kind|is_value_kind %}
{{kind|cpp_wrapper_proto_type(add_same_module_namespaces=true)}} tmp_{{name}};
mojolpm_result &= ToProto(input->get_{{raw_name}}(), tmp_{{name}});
new_instance->set_m_{{name}}(tmp_{{name}});
{%- elif kind|is_any_interface_kind %}
{{kind|cpp_wrapper_proto_type(add_same_module_namespaces=true)}} tmp_{{name}};
mojolpm_result &= ToProto(std::move(input->get_{{raw_name}}()), tmp_{{name}});
new_instance->set_m_{{name}}(tmp_{{name}});
{%- elif kind|is_nullable_kind %}
if ({{util.not_null(kind, 'input->get_' ~ raw_name ~ '()')}}) {
{%- if kind|is_move_only_kind %}
mojolpm_result &= ToProto(std::move({{util.value(kind, 'input->get_' ~ raw_name ~ '()')}}), *new_instance->mutable_m_{{name}}());
{%- else %}
mojolpm_result &= ToProto({{util.value(kind, 'input->get_' ~ raw_name ~ '()')}}, *new_instance->mutable_m_{{name}}());
{%- endif %}
}
{%- elif kind|is_move_only_kind %}
mojolpm_result &= ToProto(std::move(input->get_{{raw_name}}()), *new_instance->mutable_m_{{name}}());
{%- else %}
mojolpm_result &= ToProto(input->get_{{raw_name}}(), *new_instance->mutable_m_{{name}}());
{%- endif %}
} break;
{%- endfor %}
}
return mojolpm_result;
{%- endif %}
}{{"\n"-}}
{%- endmacro %}