blob: 4084098820451d0feed59b35a8ed6bfb6f0ed820 [file] [log] [blame]
{% 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 %}