| {% 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() |
| {% elif kind|is_union %} |
| encoder.WriteNullUnion() |
| {% else %} |
| encoder.WriteNullPointer() |
| {% endif %} |
| } else { |
| {% if not kind|is_union %} |
| {% set value = '(*'~value~')' %} |
| {% endif %} |
| {{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 |
| } |
| {% elif kind|is_union and not kind|is_nullable %} |
| if {{value}} == nil { |
| return &bindings.ValidationError{bindings.UnexpectedNullUnion, "unexpected null union"} |
| } |
| {% endif %} |
| {% if kind|is_struct or kind|is_union %} |
| 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}} |
| if encoder.Deterministic() { |
| for key{{level}}, _ := range {{value}} { |
| keys{{level}} = append(keys{{level}}, key{{level}}) |
| } |
| bindings.SortMapKeys(&keys{{level}}) |
| values{{level}} = make({{kind.value_kind|array|go_type}}, len(keys{{level}})) |
| for i, key := range keys{{level}} { |
| values{{level}}[i] = {{value}}[key] |
| } |
| } else { |
| 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_union %} |
| var err error |
| {% set decoding_function = ('Decode'~ kind|unqualified_name)|qualified(kind|package) %} |
| {{value}}, err = {{decoding_function}}(decoder) |
| if err != nil { |
| return err |
| } |
| {% if not kind|is_nullable %} |
| if {{value}} == nil { |
| return &bindings.ValidationError{bindings.UnexpectedNullUnion, "unexpected null union"} |
| } |
| {% 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 %} |