blob: b589ae91475ab262559f5cf378bc558dcebdc074 [file] [log] [blame]
{%- set data_view = union|get_qualified_name_for_kind ~ "DataView" %}
{%- set data_type = union|get_qualified_name_for_kind(internal=True) %}
namespace internal {
template <typename MaybeConstUserType>
struct Serializer<{{data_view}}, MaybeConstUserType> {
using UserType = typename std::remove_const<MaybeConstUserType>::type;
using Traits = UnionTraits<{{data_view}}, UserType>;
static size_t PrepareToSerialize(MaybeConstUserType& input,
bool inlined,
SerializationContext* context) {
size_t size = inlined ? 0 : sizeof({{data_type}});
if (CallIsNullIfExists<Traits>(input))
return size;
void* custom_context = CustomContextHelper<Traits>::SetUp(input, context);
ALLOW_UNUSED_LOCAL(custom_context);
switch (CallWithContext(Traits::GetTag, input, custom_context)) {
{%- for field in union.fields %}
{%- set name = field.name %}
case {{data_view}}::Tag::{{name|upper}}: {
{%- if field.kind|is_object_kind or field.kind|is_associated_kind %}
{%- set kind = field.kind %}
{%- set serializer_type = kind|unmapped_type_for_serializer %}
decltype(CallWithContext(Traits::{{name}}, input, custom_context))
in_{{name}} = CallWithContext(Traits::{{name}}, input,
custom_context);
{%- if kind|is_union_kind %}
size += mojo::internal::PrepareToSerialize<{{serializer_type}}>(
in_{{name}}, false, context);
{%- else %}
size += mojo::internal::PrepareToSerialize<{{serializer_type}}>(
in_{{name}}, context);
{%- endif %}
{%- endif %}
break;
}
{%- endfor %}
}
return size;
}
static void Serialize(MaybeConstUserType& input,
Buffer* buffer,
{{data_type}}** output,
bool inlined,
SerializationContext* context) {
if (CallIsNullIfExists<Traits>(input)) {
if (inlined)
(*output)->set_null();
else
*output = nullptr;
return;
}
void* custom_context = CustomContextHelper<Traits>::GetNext(context);
if (!inlined)
*output = {{data_type}}::New(buffer);
{{data_type}}* result = *output;
ALLOW_UNUSED_LOCAL(result);
// TODO(azani): Handle unknown and objects.
// Set the not-null flag.
result->size = kUnionDataSize;
result->tag = CallWithContext(Traits::GetTag, input, custom_context);
switch (result->tag) {
{%- for field in union.fields %}
{%- set name = field.name %}
{%- set kind = field.kind %}
{%- set serializer_type = kind|unmapped_type_for_serializer %}
case {{data_view}}::Tag::{{field.name|upper}}: {
decltype(CallWithContext(Traits::{{name}}, input, custom_context))
in_{{name}} = CallWithContext(Traits::{{name}}, input,
custom_context);
{%- if kind|is_object_kind %}
typename decltype(result->data.f_{{name}})::BaseType* ptr;
{%- if kind|is_union_kind %}
mojo::internal::Serialize<{{serializer_type}}>(
in_{{name}}, buffer, &ptr, false, context);
{%- elif kind|is_array_kind or kind|is_map_kind %}
const ContainerValidateParams {{name}}_validate_params(
{{kind|get_container_validate_params_ctor_args|indent(16)}});
mojo::internal::Serialize<{{serializer_type}}>(
in_{{name}}, buffer, &ptr, &{{name}}_validate_params, context);
{%- else %}
mojo::internal::Serialize<{{serializer_type}}>(
in_{{name}}, buffer, &ptr, context);
{%- endif %}
result->data.f_{{name}}.Set(ptr);
{%- if not kind|is_nullable_kind %}
MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
!ptr, mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
"null {{name}} in {{union.name}} union");
{%- endif %}
{%- elif kind|is_any_handle_or_interface_kind %}
mojo::internal::Serialize<{{serializer_type}}>(
in_{{name}}, &result->data.f_{{name}}, context);
{%- if not kind|is_nullable_kind %}
MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(
!mojo::internal::IsHandleOrInterfaceValid(result->data.f_{{name}}),
{%- if kind|is_associated_kind %}
mojo::internal::VALIDATION_ERROR_UNEXPECTED_INVALID_INTERFACE_ID,
{%- else %}
mojo::internal::VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE,
{%- endif %}
"invalid {{name}} in {{union.name}} union");
{%- endif %}
{%- elif kind|is_enum_kind %}
mojo::internal::Serialize<{{serializer_type}}>(
in_{{name}}, &result->data.f_{{name}});
{%- else %}
result->data.f_{{name}} = in_{{name}};
{%- endif %}
break;
}
{%- endfor %}
}
CustomContextHelper<Traits>::TearDown(input, custom_context);
}
static bool Deserialize({{data_type}}* input,
UserType* output,
SerializationContext* context) {
if (!input || input->is_null())
return CallSetToNullIfExists<Traits>(output);
{{data_view}} data_view(input, context);
return Traits::Read(data_view, output);
}
};
} // namespace internal