Index: third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/struct.tmpl |
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/struct.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/struct.tmpl |
index 444ffdb26e4cb0eb0b24f02fa4f93e0beb5cf418..f523ba6b8589ec3fab2a76801e28e4f3fd48f2f0 100644 |
--- a/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/struct.tmpl |
+++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/struct.tmpl |
@@ -2,8 +2,6 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
-{% import "encoding_macros.tmpl" as encoding_macros %} |
- |
{% macro define(struct, exported=True) %} |
type {{struct|name(exported)}} struct { |
{% for field in struct.fields %} |
@@ -16,7 +14,7 @@ func (s *{{struct|name(exported)}}) Encode(encoder *bindings.Encoder) error { |
encoder.StartStruct({{struct.versions[-1].num_bytes - HEADER_SIZE}}, {{struct.versions[-1].version}}) |
{% for byte in struct.bytes %} |
{% for packed_field in byte.packed_fields %} |
- {{encoding_macros.encode('s.'~packed_field.field|name(exported), packed_field.field.kind)|tab_indent()}} |
+ {{encode('s.'~packed_field.field|name(exported), packed_field.field.kind)|tab_indent()}} |
{% endfor %} |
{% endfor %} |
if err := encoder.Finish(); err != nil { |
@@ -53,7 +51,7 @@ func (s *{{struct|name(exported)}}) Decode(decoder *bindings.Decoder) error { |
{% for byte in struct.bytes %} |
{% for packed_field in byte.packed_fields %} |
if header.ElementsOrVersion >= {{packed_field.min_version}} { |
- {{encoding_macros.decode('s.'~packed_field.field|name(exported), packed_field.field.kind)|tab_indent(2)}} |
+ {{decode('s.'~packed_field.field|name(exported), packed_field.field.kind)|tab_indent(2)}} |
} |
{% endfor %} |
{% endfor %} |
@@ -64,3 +62,194 @@ func (s *{{struct|name(exported)}}) Decode(decoder *bindings.Decoder) error { |
} |
{% endmacro %} |
+ |
+ |
+ |
+{% macro encode(value, kind, level=0) %} |
+{% if kind|is_nullable %} |
+if {{value}} == nil { |
+{% if kind|is_interface %} |
+ encoder.WriteInvalidInterface() |
+{% elif kind|is_handle %} |
+ encoder.WriteInvalidHandle() |
+{% else %} |
+ encoder.WriteNullPointer() |
+{% endif %} |
+} else { |
+ {{encodeNonNullable('(*'~value~')', kind, level)|tab_indent()}} |
+} |
+{% else -%} |
+{{encodeNonNullable(value, kind, level)}} |
+{%- endif %} |
+{% endmacro %} |
+ |
+ |
+ |
+{% macro encodeNonNullable(value, kind, level=0) %} |
+{% if kind|is_pointer %} |
+if err := encoder.WritePointer(); err != nil { |
+ return err |
+} |
+{% endif %} |
+{% if kind|is_struct %} |
+if err := {{value}}.Encode(encoder); err != nil { |
+ return err |
+} |
+{% elif kind|is_array %} |
+encoder.StartArray(uint32(len({{value}})), {{kind.kind|bit_size}}) |
+for _, elem{{level}} := range {{value}} { |
+ {{encode('elem'~level, kind.kind, level+1)|tab_indent()}} |
+} |
+if err := encoder.Finish(); err != nil { |
+ return err |
+} |
+{% elif kind|is_map %} |
+encoder.StartMap() |
+{ |
+ var keys{{level}} {{kind.key_kind|array|go_type}} |
+ var values{{level}} {{kind.value_kind|array|go_type}} |
+ for key{{level}}, value{{level}} := range {{value}} { |
+ keys{{level}} = append(keys{{level}}, key{{level}}) |
+ values{{level}} = append(values{{level}}, value{{level}}) |
+ } |
+ {{encode('keys'~level, kind.key_kind|array, level+1)|tab_indent()}} |
+ {{encode('values'~level, kind.value_kind|array, level+1)|tab_indent()}} |
+} |
+if err := encoder.Finish(); err != nil { |
+ return err |
+} |
+{% elif kind|is_enum %} |
+if err := encoder.WriteInt32(int32({{value}})); err != nil { |
+ return err |
+} |
+{% elif kind|is_interface %} |
+if err := encoder.WriteInterface({{value}}.PassMessagePipe()); err != nil { |
+ return err |
+} |
+{% elif kind|is_interface_request %} |
+if err := encoder.WriteHandle({{value}}.PassMessagePipe()); err != nil { |
+ return err |
+} |
+{% else %} |
+if err := encoder.Write{{kind|encode_suffix}}({{value}}); err != nil { |
+ return err |
+} |
+{% endif %} |
+{% endmacro %} |
+ |
+ |
+ |
+{% macro decode(value, kind, level=0) %} |
+{% if kind|is_pointer %} |
+pointer{{level}}, err := decoder.ReadPointer() |
+if err != nil { |
+ return err |
+} |
+if pointer{{level}} == 0 { |
+{% if kind|is_nullable %} |
+ {{value}} = nil |
+} else { |
+ {{value}} = new({{kind|go_type(False)}}) |
+ {{decodePointerValue('(*'~value~')', kind, level)|tab_indent()}} |
+} |
+{% else %} |
+ return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"} |
+} else { |
+ {{decodePointerValue(value, kind, level)|tab_indent()}} |
+} |
+{% endif %} |
+{% elif kind|is_handle or kind|is_interface %} |
+handle{{level}}, err := decoder.Read{{kind|decode_suffix}}() |
+if err != nil { |
+ return err |
+} |
+if handle{{level}}.IsValid() { |
+{% if kind|is_interface or kind|is_interface_request %} |
+ handleOwner := bindings.NewMessagePipeHandleOwner(handle{{level}}) |
+ {{value}} = {% if kind|is_nullable %}&{% endif %}{{kind|go_type(False)}}{handleOwner} |
+{% else %} |
+ {{value}} = {% if kind|is_nullable %}&{% endif %}handle{{level}} |
+{% endif %} |
+} else { |
+{% if kind|is_nullable %} |
+ {{value}} = nil |
+{% else %} |
+ return &bindings.ValidationError{bindings.UnexpectedInvalidHandle, "unexpected invalid handle"} |
+{% endif %} |
+} |
+{% elif kind|is_enum %} |
+value{{level}}, err := decoder.Read{{kind|decode_suffix}}() |
+if err != nil { |
+ return err |
+} |
+{{value}} = {% if kind|is_nullable %}&{% endif %}{{kind|go_type(False)}}(value{{level}}) |
+{% else %} |
+value{{level}}, err := decoder.Read{{kind|decode_suffix}}() |
+if err != nil { |
+ return err |
+} |
+{{value}} = {% if kind|is_nullable %}&{% endif %}value{{level}} |
+{% endif %} |
+{% endmacro %} |
+ |
+ |
+ |
+{% macro decodePointerValue(value, kind, level=0) %} |
+{% if kind|is_struct %} |
+if err := {{value}}.Decode(decoder); err != nil { |
+ return err |
+} |
+{% elif kind|is_array %} |
+len{{level}}, err := decoder.StartArray({{kind.kind|bit_size}}) |
+if err != nil { |
+ return err |
+} |
+{% if kind.length %} |
+if len{{level}} != {{kind.length}} { |
+ return &bindings.ValidationError{bindings.UnexpectedArrayHeader, |
+ fmt.Sprintf("invalid array length: expected %d, got %d", {{kind.length}}, len{{level}}), |
+ } |
+} |
+{% else %} |
+{{value}} = make({{kind|go_type(False)}}, len{{level}}) |
+{% endif %} |
+for i{{level}} := uint32(0); i{{level}} < len{{level}}; i{{level}}++ { |
+ {{decode(value~'[i'~level~']', kind.kind, level+1)|tab_indent()}} |
+} |
+if err := decoder.Finish(); err != nil { |
+ return err |
+} |
+{% elif kind|is_map %} |
+if err := decoder.StartMap(); err != nil { |
+ return err |
+} |
+var keys{{level}} {{kind.key_kind|array|go_type}} |
+{ |
+ {{decode('keys'~level, kind.key_kind|array, level+1)|tab_indent()}} |
+} |
+var values{{level}} {{kind.value_kind|array|go_type}} |
+{ |
+ {{decode('values'~level, kind.value_kind|array, level+1)|tab_indent()}} |
+} |
+if len(keys{{level}}) != len(values{{level}}) { |
+ return &bindings.ValidationError{bindings.DifferentSizedArraysInMap, |
+ fmt.Sprintf("Number of keys %d is different from number of values %d", len(keys{{level}}), len(values{{level}})), |
+ } |
+} |
+if err := decoder.Finish(); err != nil { |
+ return err |
+} |
+len{{level}} := len(keys{{level}}) |
+map{{level}} := make({{kind|go_type(False)}}) |
+for i{{level}} := 0; i{{level}} < len{{level}}; i{{level}}++ { |
+ map{{level}}[keys{{level}}[i{{level}}]] = values{{level}}[i{{level}}] |
+} |
+{{value}} = map{{level}} |
+{% else %} |
+value{{level}}, err := decoder.Read{{kind|decode_suffix}}() |
+if err != nil { |
+ return err |
+} |
+{{value}} = value{{level}} |
+{% endif %} |
+{% endmacro %} |