| {# TODO(yzshen): Make these templates more readable. #} |
| |
| {# Computes the serialized size for the specified struct. |
| |struct| is the struct definition. |
| |input_field_pattern| should be a pattern that contains one string |
| placeholder, for example, "input->%s", "p_%s". The placeholder will be |
| substituted with struct field names to refer to the input fields. |
| |context| is the name of the serialization context. |
| |input_may_be_temp| indicates whether any input may be temporary obejcts. |
| We need to assign temporary objects to local variables before passing it to |
| Serializer, because it is illegal to pass temporary objects as non-const |
| references. |
| This macro is expanded to compute seriailized size for both: |
| - user-defined structs: the input is an instance of the corresponding struct |
| wrapper class. |
| - method parameters/response parameters: the input is a list of |
| arguments. |
| It declares |size| of type size_t to store the resulting size. #} |
| {%- macro get_serialized_size(struct, input_field_pattern, context, |
| input_may_be_temp=False) -%} |
| size_t size = sizeof({{struct|get_qualified_name_for_kind(internal=True)}}); |
| {%- for pf in struct.packed.packed_fields_in_ordinal_order |
| if pf.field.kind|is_object_kind or pf.field.kind|is_associated_kind %} |
| {%- set name = pf.field.name -%} |
| {%- set kind = pf.field.kind -%} |
| {%- set original_input_field = input_field_pattern|format(name) %} |
| {%- set input_field = "in_%s"|format(name) if input_may_be_temp |
| else original_input_field %} |
| {%- if input_may_be_temp %} |
| decltype({{original_input_field}}) in_{{name}} = {{original_input_field}}; |
| {%- endif %} |
| |
| {%- set serializer_type = kind|unmapped_type_for_serializer %} |
| {%- if kind|is_union_kind %} |
| size += mojo::internal::PrepareToSerialize<{{serializer_type}}>( |
| {{input_field}}, true, {{context}}); |
| {%- else %} |
| size += mojo::internal::PrepareToSerialize<{{serializer_type}}>( |
| {{input_field}}, {{context}}); |
| {%- endif %} |
| {%- endfor %} |
| {%- endmacro -%} |
| |
| {# Serializes the specified struct. |
| |struct| is the struct definition. |
| |struct_display_name| is the display name for the struct that can be showed |
| in error/log messages, for example, "FooStruct", "FooMethod request". |
| |input_field_pattern| should be a pattern that contains one string |
| placeholder, for example, "input->%s", "p_%s". The placeholder will be |
| substituted with struct field names to refer to the input fields. |
| |output| is the name of the output struct instance. |
| |buffer| is the name of the Buffer instance used. |
| |context| is the name of the serialization context. |
| |input_may_be_temp|: please see the comments of get_serialized_size. |
| This macro is expanded to do serialization for both: |
| - user-defined structs: the input is an instance of the corresponding struct |
| wrapper class. |
| - method parameters/response parameters: the input is a list of |
| arguments. #} |
| {%- macro serialize(struct, struct_display_name, input_field_pattern, output, |
| buffer, context, input_may_be_temp=False) -%} |
| auto {{output}} = |
| {{struct|get_qualified_name_for_kind(internal=True)}}::New({{buffer}}); |
| ALLOW_UNUSED_LOCAL({{output}}); |
| {%- for pf in struct.packed.packed_fields_in_ordinal_order %} |
| {%- set input_field = input_field_pattern|format(pf.field.name) %} |
| {%- set name = pf.field.name %} |
| {%- set kind = pf.field.kind %} |
| {%- set serializer_type = kind|unmapped_type_for_serializer %} |
| |
| {%- if kind|is_object_kind or kind|is_any_handle_or_interface_kind %} |
| {%- set original_input_field = input_field_pattern|format(name) %} |
| {%- set input_field = "in_%s"|format(name) if input_may_be_temp |
| else original_input_field %} |
| {%- if input_may_be_temp %} |
| decltype({{original_input_field}}) in_{{name}} = {{original_input_field}}; |
| {%- endif %} |
| {%- endif %} |
| |
| {%- if kind|is_object_kind %} |
| {%- if kind|is_array_kind or kind|is_map_kind %} |
| typename decltype({{output}}->{{name}})::BaseType* {{name}}_ptr; |
| const mojo::internal::ContainerValidateParams {{name}}_validate_params( |
| {{kind|get_container_validate_params_ctor_args|indent(10)}}); |
| mojo::internal::Serialize<{{serializer_type}}>( |
| {{input_field}}, {{buffer}}, &{{name}}_ptr, &{{name}}_validate_params, |
| {{context}}); |
| {{output}}->{{name}}.Set({{name}}_ptr); |
| {%- elif kind|is_union_kind %} |
| auto {{name}}_ptr = &{{output}}->{{name}}; |
| mojo::internal::Serialize<{{serializer_type}}>( |
| {{input_field}}, {{buffer}}, &{{name}}_ptr, true, {{context}}); |
| {%- else %} |
| typename decltype({{output}}->{{name}})::BaseType* {{name}}_ptr; |
| mojo::internal::Serialize<{{serializer_type}}>( |
| {{input_field}}, {{buffer}}, &{{name}}_ptr, {{context}}); |
| {{output}}->{{name}}.Set({{name}}_ptr); |
| {%- endif %} |
| {%- if not kind|is_nullable_kind %} |
| MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( |
| {{output}}->{{name}}.is_null(), |
| mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, |
| "null {{name}} in {{struct_display_name}}"); |
| {%- endif %} |
| |
| {%- elif kind|is_any_handle_or_interface_kind %} |
| mojo::internal::Serialize<{{serializer_type}}>( |
| {{input_field}}, &{{output}}->{{name}}, {{context}}); |
| {%- if not kind|is_nullable_kind %} |
| MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( |
| !mojo::internal::IsHandleOrInterfaceValid({{output}}->{{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 {{struct_display_name}}"); |
| {%- endif %} |
| |
| {%- elif kind|is_enum_kind %} |
| mojo::internal::Serialize<{{serializer_type}}>( |
| {{input_field}}, &{{output}}->{{name}}); |
| |
| {%- else %} |
| {{output}}->{{name}} = {{input_field}}; |
| {%- endif %} |
| {%- endfor %} |
| {%- endmacro -%} |
| |
| {# Deserializes the specified struct. |
| |struct| is the struct definition. |
| |input| is the name of the input struct data view. It is expected to be |
| non-null. |
| |output_field_pattern| should be a pattern that contains one string |
| placeholder, for example, "result->%s", "p_%s". The placeholder will be |
| substituted with struct field names to refer to the output fields. |
| |context| is the name of the serialization context. |
| |success| is the name of a bool variable to track success of the operation. |
| This macro is expanded to do deserialization for both: |
| - user-defined structs: the output is an instance of the corresponding |
| struct wrapper class. |
| - method parameters/response parameters: the output is a list of |
| arguments. #} |
| {%- macro deserialize(struct, input, output_field_pattern, success) -%} |
| {%- for pf in struct.packed.packed_fields_in_ordinal_order %} |
| {%- set output_field = output_field_pattern|format(pf.field.name) %} |
| {%- set name = pf.field.name %} |
| {%- set kind = pf.field.kind %} |
| {%- if kind|is_object_kind or kind|is_enum_kind %} |
| if (!{{input}}.Read{{name|under_to_camel}}(&{{output_field}})) |
| {{success}} = false; |
| {%- elif kind|is_any_handle_kind %} |
| {{output_field}} = {{input}}.Take{{name|under_to_camel}}(); |
| {%- elif kind|is_any_interface_kind %} |
| {{output_field}} = |
| {{input}}.Take{{name|under_to_camel}}<decltype({{output_field}})>(); |
| {%- else %} |
| {{output_field}} = {{input}}.{{name}}(); |
| {%- endif %} |
| {%- endfor %} |
| {%- endmacro %} |