diff --git a/tpl/macros_msgpack.twig b/tpl/macros_msgpack.twig new file mode 100644 index 0000000..dd1789f --- /dev/null +++ b/tpl/macros_msgpack.twig @@ -0,0 +1,132 @@ +{% macro msgpack_decode(name, fields) %} +func (s *{{ name }}) DecodeMsgpack(dec *msgpack.Decoder) error { + l, err := dec.DecodeMapLen() + if err != nil { + return errors.WithStack(err) + } + + for i := 0; i < l; i++ { + field, err := dec.DecodeString() + if err != nil { + return errors.WithStack(err) + } + + switch field { + {%~ for f in fields %} + case "{{ f|alias }}": + {{ _self.msgpack_value_decode(f.type, 's.' ~ f|fname) }} + {%~ endfor %} + default: + return errors.Errorf("unexpected field `%s`", field) + } + } + + return nil +} +{% endmacro msgpack_decode %} + + +{% macro msgpack_value_decode(type, varname) %} +{%~ if type is builtin %} + v, err := dec.Decode{{ type|builtin_type_suffix }}() + if err != nil { + return errors.WithStack(err) + } + {{ varname }} = v +{%~ elseif type is enum %} + v, err := dec.DecodeInt32() + if err != nil { + return errors.WithStack(err) + } + {{ varname }} = {{ type.name }}(v) + if !{{ varname }}.IsValid() { + return errors.Errorf("bad enum value `%d` for `%s`", {{ varname }}, "{{ type.name }}") + } +{%~ elseif type is struct %} + if err := {{ varname }}.DecodeMsgpack(dec); err != nil { + return err + } +{%~ elseif type is array %} + size, err := dec.DecodeArrayLen() + if err != nil { + return errors.WithStack(err) + } + + for ; size > 0; size-- { + var tmp {{ type.value|go_type }} + {{ _self.msgpack_value_decode(type.value, 'tmp') }} + {{ varname }} = append({{ varname }}, tmp) + } +{%~ else %} + {{ Error('unexpected type ' ~ type) }} +{%~ endif %} +{% endmacro msgpack_value_decode %} + + +{% macro msgpack_encode(name, fields) %} +func (s *{{ name }}) EncodeMsgpack(enc *msgpack.Encoder) error { + if err := enc.EncodeMapLen({{ fields|length }}); err != nil { + return errors.WithStack(err) + } + + {% for f in fields -%} + + if err := enc.EncodeString("{{ f|alias }}"); err != nil { + return errors.WithStack(err) + } + {{ _self.msgpack_value_encode(f.type, 's.' ~ f|fname) }} + {% endfor %} + + return nil +} +{% endmacro msgpack_encode %} + + +{% macro msgpack_value_encode(type, varname) %} +{%~ if type is int %} + if err := enc.EncodeInt(int64({{ varname }})); err != nil { + return errors.WithStack(err) + } +{%~ elseif type is uint %} + if err := enc.EncodeUint(uint64({{ varname }})); err != nil { + return errors.WithStack(err) + } +{%~ elseif type is float %} + if err := enc.EncodeFloat32({{ varname }}); err != nil { + return errors.WithStack(err) + } +{%~ elseif type is double %} + if err := enc.EncodeFloat64({{ varname }}); err != nil { + return errors.WithStack(err) + } +{%~ elseif type is bool %} + if err := enc.EncodeBool({{ varname }}); err != nil { + return errors.WithStack(err) + } +{%~ elseif type is string %} + if err := enc.EncodeString({{ varname }}); err != nil { + return errors.WithStack(err) + } +{%~ elseif type is blob %} + if err := enc.EncodeBytes({{ varname }}); err != nil { + return errors.WithStack(err) + } +{%~ elseif type is enum %} + if err := enc.EncodeInt(int64({{ varname }})); err != nil { + return errors.WithStack(err) + } +{%~ elseif type is struct %} + if err := {{ varname }}.EncodeMsgpack(enc); err != nil { + return errors.WithStack(err) + } +{%~ elseif type is array %} + if err := enc.EncodeArrayLen(len({{ varname }})); err != nil { + return errors.WithStack(err) + } + for _, v := range {{ varname }} { + {{ _self.msgpack_value_encode(type.value, 'v') }} + } +{%~ else %} + {{ Error('unexpected type ' ~ type) }} +{%~ endif %} +{% endmacro msgpack_value_encode %} diff --git a/tpl/macros_struct.twig b/tpl/macros_struct.twig index eb3ae2b..190a5b1 100644 --- a/tpl/macros_struct.twig +++ b/tpl/macros_struct.twig @@ -960,191 +960,3 @@ func (s *{{ name }}) FieldsMask() meta.FieldsMask { return s.fieldsMask } {% endmacro bitfields_methods %} - - -{% macro msgpack_decode(name, fields) %} -func (s *{{ name }}) DecodeMsgpack(dec *msgpack.Decoder) error { - l, err := dec.DecodeMapLen() - if err != nil { - return errors.WithStack(err) - } - - for i := 0; i < l; i++ { - field, err := dec.DecodeString() - if err != nil { - return errors.WithStack(err) - } - - switch field { - {%~ for f in fields %} - case "{{ f|alias }}": - {{ _self.msgpack_value_decode(f.type, 's.' ~ f|fname) }} - {%~ endfor %} - default: - return errors.Errorf("unexpected field `%s`", field) - } - } - - return nil -} -{% endmacro msgpack_decode %} - - -{% macro msgpack_value_decode(type, varname) %} -{%~ if type is builtin %} - v, err := dec.Decode{{ type|builtin_type_suffix }}() - if err != nil { - return errors.WithStack(err) - } - {{ varname }} = v -{%~ elseif type is enum %} - v, err := dec.DecodeInt32() - if err != nil { - return errors.WithStack(err) - } - {{ varname }} = {{ type.name }}(v) - if !{{ varname }}.IsValid() { - return errors.Errorf("bad enum value `%d` for `%s`", {{ varname }}, "{{ type.name }}") - } -{%~ elseif type is struct %} - if err := {{ varname }}.DecodeMsgpack(dec); err != nil { - return err - } -{%~ elseif type is array %} - size, err := dec.DecodeArrayLen() - if err != nil { - return errors.WithStack(err) - } - - for ; size > 0; size-- { - var tmp {{ type.value|go_type }} - {{ _self.msgpack_value_decode(type.value, 'tmp') }} - {{ varname }} = append({{ varname }}, tmp) - } -{%~ else %} - {{ Error('unexpected type ' ~ type) }} -{%~ endif %} -{% endmacro msgpack_value_decode %} - - -{% macro msgpack_encode(name, fields) %} -func (s *{{ name }}) EncodeMsgpack(enc *msgpack.Encoder) error { - if err := enc.EncodeMapLen({{ fields|length }}); err != nil { - return errors.WithStack(err) - } - - {% for f in fields -%} - - if err := enc.EncodeString("{{ f|alias }}"); err != nil { - return errors.WithStack(err) - } - {{ _self.msgpack_value_encode(f.type, 's.' ~ f|fname) }} - {% endfor %} - - return nil -} -{% endmacro msgpack_encode %} - - -{% macro msgpack_value_encode(type, varname) %} -{%~ if type is int %} - if err := enc.EncodeInt(int64({{ varname }})); err != nil { - return errors.WithStack(err) - } -{%~ elseif type is uint %} - if err := enc.EncodeUint(uint64({{ varname }})); err != nil { - return errors.WithStack(err) - } -{%~ elseif type is float %} - if err := enc.EncodeFloat32({{ varname }}); err != nil { - return errors.WithStack(err) - } -{%~ elseif type is double %} - if err := enc.EncodeFloat64({{ varname }}); err != nil { - return errors.WithStack(err) - } -{%~ elseif type is bool %} - if err := enc.EncodeBool({{ varname }}); err != nil { - return errors.WithStack(err) - } -{%~ elseif type is string %} - if err := enc.EncodeString({{ varname }}); err != nil { - return errors.WithStack(err) - } -{%~ elseif type is blob %} - if err := enc.EncodeBytes({{ varname }}); err != nil { - return errors.WithStack(err) - } -{%~ elseif type is enum %} - if err := enc.EncodeInt(int64({{ varname }})); err != nil { - return errors.WithStack(err) - } -{%~ elseif type is struct %} - if err := {{ varname }}.EncodeMsgpack(enc); err != nil { - return errors.WithStack(err) - } -{%~ elseif type is array %} - if err := enc.EncodeArrayLen(len({{ varname }})); err != nil { - return errors.WithStack(err) - } - for _, v := range {{ varname }} { - {{ _self.msgpack_value_encode(type.value, 'v') }} - } -{%~ else %} - {{ Error('unexpected type ' ~ type) }} -{%~ endif %} -{% endmacro msgpack_value_encode %} - - -{% macro struct_required_fields(name, fields) %} -var _{{ name }}RequiredFields map[string]struct{} -func init() { - _{{ name }}RequiredFields = map[string]struct{}{ - {% for f in fields|filter(f => not has_token(f, 'optional')) %} - "{{ f|alias }}": {}, - {% endfor %} - } -} -{% endmacro struct_required_fields %} - - -{% macro meta_read_assoc(s, name) %} -{% set all_fields = get_all_fields(s) %} -func (s *{{ name|default(s.name) }}) readFieldsAssociative(reader meta.Reader) error { - size, err := reader.ContainerSize() - if err != nil { - return err - } - - readFields := make(map[string]struct{}, {{ all_fields|length }}) - for ; size > 0; size-- { - var field string - if err := reader.ReadString(&field, ""); err != nil { - return err - } - - switch field { - {% for f in all_fields %} - case "{{ f|alias }}": - {{ _self.meta_read_field(f.type, 's.' ~ f|fname, f|alias, f.tokens) }} - {% endfor %} - default: - {# continue // do not return an error for nested structs #} - return errors.Errorf("unexpected field `%s`", field) - } - - readFields[field] = struct{}{} - {% if has_token(s, 'table') %} - s.changedFields.SetChanged(field) - {% endif %} - } - - for field := range _{{ name|default(s.name) }}RequiredFields { - if _, ok := readFields[field]; !ok { - return errors.Errorf("field `%s` is not present", field) - } - } - - return nil -} -{% endmacro meta_read_assoc %}