virtual token support. unused code removed

This commit is contained in:
Pavel Merzlyakov 2023-09-01 17:45:20 +03:00
parent 63297519da
commit d109355790
5 changed files with 62 additions and 708 deletions

View File

@ -119,7 +119,7 @@ function add_twig_filters(\Twig\Environment $twig)
{
$twig->addFilter(new TwigFilter(
'go_type',
fn(\mtgType $t): string => go_type($t),
fn(\mtgType $t, array $tokens = []): string => go_type($t, $tokens),
));
$twig->addFilter(new TwigFilter(
'ucfirst',
@ -204,11 +204,6 @@ function add_twig_filters(\Twig\Environment $twig)
return $fields;
}
));
$twig->addFilter(new TwigFilter(
'rpc_invert',
fn(string $name): string => rpc_invert($name),
));
}
function add_twig_functions(\Twig\Environment $twig)
@ -271,25 +266,6 @@ function add_twig_functions(\Twig\Environment $twig)
return parse_meta_field($str, $meta);
}
));
$twig->addFunction(new TwigFunction('field_reset',
function($name, $type, $tokens)
{
return field_reset($name, $type, $tokens);
}
));
$twig->addFunction(new TwigFunction('buf2var',
function($name, $fname, $type, $buf, $tokens, $is_ptr)
{
return buf2var($name, $fname, $type, $buf, $tokens, $is_ptr);
}
));
$twig->addFunction(new TwigFunction('var2buf',
function($name, $fname, $type, $buf, $tokens, $is_ptr)
{
return var2buf($name, $fname, $type, $buf, $tokens, $is_ptr);
}
));
}
function snake2camel(string $str): string
@ -300,9 +276,16 @@ function snake2camel(string $str): string
function go_type(\mtgType $type, array $tokens = []): string
{
if($type instanceof \mtgMetaEnum)
{
return $type->getName();
}
else if($type instanceof \mtgMetaStruct)
{
if(array_key_exists('virtual', $tokens)) {
return 'I'.$type->getName();
}
return $type->getName();
}
else if($type instanceof \mtgBuiltinType)
{
if($type->isFloat())
@ -316,9 +299,9 @@ function go_type(\mtgType $type, array $tokens = []): string
}
else if($type instanceof \mtgArrType)
{
$native = go_type($type->getValue());
$native = go_type($type->getValue(), $tokens);
return "[]$native";
}
}
else
throw new Exception("Unknown type '{$type->getName()}'");
}
@ -367,204 +350,3 @@ function parse_meta_field(string $str, \mtgMetaInfo $meta): \mtgMetaField
list($name, $type) = explode('|', $str);
return new \mtgMetaField($name, new \mtgTypeRef(new \mtgBuiltinType($type)));
}
function builtin_type_prefix(\mtgBuiltinType $type)
{
switch($type->getName())
{
case "string":
return "String";
case "bool":
return "Bool";
case "blob":
return "Blob";
case "float":
return "Float";
case "double":
return "Double";
case "uint64":
return "U64";
case "int64":
return "I64";
case "uint":
case "uint32":
return "U32";
case "uint16":
return "U16";
case "uint8":
return "U8";
case "int":
case "int32":
return "I32";
case "int16":
return "I16";
case "int8":
return "I8";
default:
throw new Exception("Unknown type '{$type}'");
}
}
function field_reset($name, \mtgType $type, array $tokens)
{
$str = '';
if($type instanceof \mtgBuiltinType)
{
if($type->isNumeric())
{
if(array_key_exists('default', $tokens) && is_numeric($tokens['default']))
$str .= "self.$name = ".$tokens['default'];
else
$str .= " self.$name = 0";
}
else if($type->isString())
{
if(array_key_exists('default', $tokens))
$str .= "self.$name = ".$tokens['default'];
else
$str .= "self.$name = \"\"";
}
else if($type->isBool())
{
if(array_key_exists('default', $tokens))
$str .= "self.$name = ".$tokens['default'];
else
$str .= "self.$name = false";
}
else if($type->isBlob())
{
if(array_key_exists('default', $tokens))
$str .= "self.$name = ".$tokens['default'];
else
$str .= "self.$name = nil";
}
else
throw new Exception("Unknown type '$type'");
}
else if($type instanceof \mtgArrType)
{
$str = "if self.$name == nil { \nself.$name = make(".go_type($type, $tokens).",0) \n}\n ";
$str .= "self.$name = self.{$name}[0:0]";
}
else if($type instanceof \mtgMetaEnum)
{
if(array_key_exists('default', $tokens))
$str = "self.$name = ".go_type($type, $tokens)."_".trim($tokens['default'], '"');
else
$str = "self.$name = 0";
}
else if($type instanceof \mtgMetaStruct)
{
$is_virtual = array_key_exists("virtual", $tokens);
if($is_virtual)
$str .= "self.$name = New".ltrim(go_type($type, $tokens),'I')."() ";
else
$str .= "self.$name.Reset()";
}
else
throw new Exception("Unknown type '{$type->getName()}'");
return $str;
}
function buf2var($name, $fname, \mtgType $type, $buf, array $tokens = array(), $is_ptr = false)
{
$str = '';
if($type instanceof \mtgBuiltinType)
{
$str .= _read_op($tokens, $buf.'.Read'.builtin_type_prefix($type).'(&'.$fname.', "'.$name.'")');
}
else if($type instanceof \mtgMetaEnum)
{
$str .= _read_op($tokens, "{$buf}.ReadI32((*int32)(&{$fname}), \"$name\")");
$str .= "\n if !{$fname}.IsValid() { return errors.Errorf(\"Bad enum value %d for $name\", $fname) }";
}
else if($type instanceof \mtgMetaStruct)
{
if(array_key_exists('virtual', $tokens))
$str .= "if v, err := meta.ReadStructGeneric($buf, CreateById, \"{$name}\"); err != nil { return err } else { {$fname} = v.(I{$type}) }";
else
$str .= _read_op($tokens, "meta.ReadStruct($buf, ".($is_ptr?"":"&")."$fname, \"$name\")");
}
else if($type instanceof \mtgArrType)
{
$is_virtual = array_key_exists("virtual", $tokens);
$native_type = go_type($type->getValue(), $tokens);
$offset = "\n ";
$str .= "/*[]{$name}*/";
$str .= $offset . _read_op($tokens, "{$buf}.BeginContainer(\"$name\")");
$str .= $offset . "_{$name}_size, err := {$buf}.GetContainerSize()";
$str .= $offset . "if err != nil { return err }";
$need_new = !$is_virtual && $type->getValue() instanceof \mtgMetaStruct;
$str .= $offset . "for ; _{$name}_size > 0; _{$name}_size-- {";
$offset = "\n ";
$str .= $offset . "var tmp_{$name} {$native_type}";
$str .= $offset . buf2var("", "tmp_{$name}", $type->getValue(), $buf, $tokens, $is_virtual);
$str .= $offset . "{$fname} = append({$fname}, tmp_{$name})";
$offset = "\n ";
$str .= $offset . "}";
$str .= $offset . _read_op($tokens, "{$buf}.EndContainer()");
$str .= "\n";
}
else
throw new Exception("Unknown type '{$type->getName()}'");
return $str;
}
function var2buf($name, $fname, \mtgType $type, $buf, array $tokens = array(), $is_ptr = false)
{
$str = '';
if($type instanceof \mtgBuiltinType)
{
$str .= _write_op("{$buf}.Write".builtin_type_prefix($type)."($fname, \"$name\")")."\n";
}
else if($type instanceof \mtgMetaEnum)
{
$str .= _write_op("{$buf}.WriteI32(int32($fname), \"$name\")");
}
else if($type instanceof \mtgMetaStruct)
{
if(array_key_exists('virtual', $tokens))
$str .= _write_op("meta.WriteStructGeneric($buf, ".($is_ptr?"":"&")."$fname, \"$name\")");
else
$str .= _write_op("meta.WriteStruct($buf, &$fname, \"$name\")");
}
else if($type instanceof \mtgArrType)
{
$str .= "{$buf}.BeginContainer(\"{$name}\")\n";
$str .= " for _, v := range({$fname}) {\n";
$str .= " ".var2buf("", "v", $type->getValue(), $buf, $tokens, true)."\n";
$str .= " }\n";
$str .= " "._write_op("{$buf}.EndContainer()")."\n";
}
else
throw new Exception("Unknown type '{$type->getName()}'");
return $str;
}
function _write_op($op)
{
return "if err := $op; err != nil { return err }";
}
function _read_op(array $tokens, $op)
{
return "if err := $op; err != nil { return err }";
}
function rpc_invert($name)
{
if(strpos($name, '_RSP_') !== false)
return str_replace('_RSP_', '_REQ_', $name);
else
return str_replace('_REQ_', '_RSP_', $name);
}

View File

@ -11,7 +11,7 @@ import (
"strconv"
"strings"
"git.bit5.ru/backend/meta/v3"
"git.bit5.ru/backend/meta/v4"
"git.bit5.ru/backend/versioning"
"git.bit5.ru/gomodules/metadb"
"github.com/go-logr/logr"
@ -50,6 +50,10 @@ func CreateById(classId uint32) (meta.Struct, error) {
}
}
func CreateReadableById(classId uint32) (meta.Readable, error) {
return CreateById(classId)
}
func CreateByName(name string) (meta.Struct, error) {
switch name {
{% for u in structs %}

View File

@ -1,464 +0,0 @@
{% macro decl_units(meta) %}
{%- for u in meta.getunits ~%}
{%- if u.object is instanceof('\\mtgMetaStruct') ~%}
{{ _self.decl_struct(u.object) }}
{%- elseif u.object is instanceof('\\mtgMetaEnum') ~%}
{{ _self.decl_enum(u.object) }}
{%- elseif u.object is instanceof('\\mtgMetaRPC') ~%}
{{ _self.decl_rpc(u.object) }}
{%- endif ~%}
{%- endfor ~%}
{% endmacro %}
{% macro decl_struct(o) %}
{%- if o.parent and has_token(o, 'POD') -%}
{{Error("@POD structs can't have a parent: " ~ o.name)}}
{%- endif -%}
{%- if o.parent and has_token(o, 'bitfields') -%}
{{Error("@bitfields structs can't have a parent: " ~ o.name)}}
{%- endif ~%}
//==============================
type {{o.name}} struct {
{% if o.parent %}
{{o.parent.name}}
{% endif %}
{{_self.decl_struct_fields(o)}}
}
var _{{o.name}}_class_props map[string]string = {{_self.props_map(o.tokens)}}
var _{{o.name}}_class_fields []string = {{_self.struct_fields_names(o)}}
var _{{o.name}}_fields_props meta.ClassFieldsProps = {{_self.struct_fields_props(o)}}
func {{o.name}}_CLASS_ID() uint32 {
return {{o.classid}}
}
type I{{o.name}} interface {
meta.IMetaStruct
Ptr{{o.name}}() *{{o.name}}
}
func (*{{o.name}}) CLASS_ID() uint32 {
return {{o.classid}}
}
func (*{{o.name}}) CLASS_NAME() string {
return "{{o.name}}"
}
func (*{{o.name}}) CLASS_PROPS() *map[string]string {
return &_{{o.name}}_class_props
}
func (*{{o.name}}) CLASS_FIELDS() []string {
return _{{o.name}}_class_fields
}
func (*{{o.name}}) CLASS_FIELDS_PROPS() *meta.ClassFieldsProps {
return &_{{o.name}}_fields_props
}
//convenience getter
func Ptr{{o.name}}(m meta.IMetaStruct) *{{o.name}} {
p, ok := m.(I{{o.name}})
if !ok {
return nil
}
return p.Ptr{{o.name}}()
}
func (self *{{o.name}}) Ptr{{o.name}}() *{{o.name}} {
return self
}
func New{{o.name}}() *{{o.name}} {
item := new ({{o.name}})
item.Reset()
return item
}
func (self *{{o.name}}) Reset() {
{{_self.struct_reset_fields(o)}}
}
func (self *{{o.name}}) Read(reader meta.Reader) error {
return meta.ReadStruct(reader, self, "")
}
func (self *{{o.name}}) ReadFields(reader meta.Reader) error {
self.Reset()
{{_self.struct_read_fields(o)}}
return nil
}
func (self *{{o.name}}) Write(writer meta.Writer) error {
return meta.WriteStruct(writer, self, "")
}
func (self *{{o.name}}) WriteFields(writer meta.Writer) error {
{{_self.struct_write_fields(o)}}
return nil
}
{% if has_token(o, 'bitfields') %}
{{_self.bitfields_methods(o)}}
{% endif %}
{% if has_token(o, 'statist') %}
{{_self.stats_methods(o)}}
{% endif %}
{% if has_token(o, 'POD') and has_token(o, 'id') and has_token(o, 'table') and has_token(o, 'owner') %}
{{_self.db_item_methods(o)}}
{% endif %}
{% endmacro %}
{%- macro props_map(tokens) -%}
map[string]string{
{%- for k,v in tokens -%}
"{{k}}" : "{{v|replace({'"' : '\\"'})}}",
{%- endfor -%}
}
{%- endmacro -%}
{%- macro struct_fields_names(o) -%}
[]string{
{%- for f in get_all_fields(o) -%}
"{{f.name}}",
{%- endfor -%}
}
{%- endmacro -%}
{%- macro struct_fields_props(o) -%}
map[string]map[string]string{
{%- for f in get_all_fields(o) -%}
"{{f.name|ucfirst}}" : {{_self.props_map(f.tokens)}},
{%- endfor -%}
}
{%- endmacro -%}
{%- macro decl_struct_fields(o) -%}
{%- for f in o.fields ~%}
{{f.name|ucfirst}} {{f.type|go_type(f.tokens)}} {{_self.field_annotations(o, f)}}
{%- endfor ~%}
{%if has_token(o, 'bitfields') %}
fieldsMask meta.FieldsMask //@bitfields support
{%- endif ~%}
{%- endmacro -%}
{%- macro field_annotations(o, f) -%}
{%- if f.name|first != '_' -%}
`json:"{{f.name}}" {% if has_token(o, 'table') -%} db:"{{f.name}}"{%- endif -%}`
{%- endif -%}
{%- endmacro -%}
{% macro struct_reset_fields(o) %}
{%- if o.parent ~%}
self.{{o.parent.name}}.Reset()
{%- endif ~%}
{%- for f in o.fields ~%}
{{field_reset(f.name|ucfirst, f.type, f.tokens)}}
{%- endfor ~%}
{% if has_token(o, 'bitfields') ~%}
self.fieldsMask = meta.FieldsMask{}
{%- endif ~%}
{% endmacro %}
{% macro struct_read_fields(o) %}
{%- if has_token(o, 'bitfields') ~%}
use_mask, mask, err := reader.TryReadMask()
if err != nil {
return err
}
self.fieldsMask = mask
{%- endif ~%}
_cont_size, err := reader.GetContainerSize()
if err != nil {
return err
}
if _cont_size < {{(o.fields|length)}} {
_cont_size = {{(o.fields|length)}}
}
{%- if o.parent ~%}
if err := self.{{o.parent.name}}.ReadFields(reader); err != nil { return err }
{%- endif ~%}
{%- for f in o.fields ~%}
if _cont_size <= 0 {
return nil
}
{%if has_token(o, 'bitfields') ~%}
if !use_mask {
{%- endif ~%}
_cont_size--
{%if has_token(o, 'bitfields') ~%}
}
if !use_mask || (use_mask && self.HasValue({{loop.index0}})) {
{%- endif ~%}
{{buf2var(f.name, 'self.' ~ f.name|ucfirst, f.type, 'reader', f.tokens, false)}}
{%if has_token(o, 'bitfields') ~%}
}
{%- endif -%}
{%- endfor -%}
{% endmacro %}
{% macro struct_write_fields(o) %}
{%- if o.parent ~%}
if err := self.{{o.parent.name}}.WriteFields(writer); err != nil { return err }
{%- endif ~%}
{%- for f in o.fields ~%}
{{var2buf(f.name, 'self.' ~ f.name|ucfirst, f.type, "writer", f.tokens, has_token(f, 'virtual'))}}
{%- endfor -%}
{% endmacro %}
{% macro bitfields_methods(o) %}
func(self *{{o.name}}) HasValue(index uint64) bool {
return self.fieldsMask.FieldChanged(index)
}
func(self *{{o.name}}) SetFieldChanged(index uint64) {
self.fieldsMask.SetFieldChanged(index)
}
func(self *{{o.name}}) IsMaskFilled() bool {
return self.fieldsMask.IsFilled()
}
func(self *{{o.name}}) GetMask() meta.FieldsMask {
return self.fieldsMask
}
{% endmacro %}
{% macro stats_methods(o) %}
func (self *{{o.name}}) Table() string {
return "{{token(o, 'statist')}}"
}
func (self * {{o.name}}) Columns() []string {
return []string{
{%- for f in get_all_fields(o) ~%}
{%- if not has_token(f, 'statist_skip') ~%}
"{{token_or(f, 'statist_alias', f.name)}}",
{%- endif ~%}
{%- endfor ~%}
}
}
func (self *{{o.name}}) Values() []interface{} {
return []interface{}{
{%- for f in get_all_fields(o) ~%}
{%- if not has_token(f, 'statist_skip') ~%}
self.{{f.name|ucfirst}},
{%- endif ~%}
{%- endfor ~%}
}
}
{% endmacro %}
{% macro db_item_methods(o) %}
func (self *{{o.name}}) NewInstance() meta.IMetaDataItem {
return New{{o.name}}()
}
func (self *{{o.name}}) GetDbTableName() string {
return "{{token(o, 'table')}}"
}
func (self *{{o.name}}) GetDbFields() []string {
return self.CLASS_FIELDS()
}
func (self *{{o.name}}) GetOwnerFieldName() string {
return "{{token(o, 'owner')}}"
}
func (self *{{o.name}}) GetIdFieldName() string {
return "{{token(o, 'id')}}"
}
func (self *{{o.name}}) GetIdValue() uint64 {
return uint64(self.{{token(o, 'id')|ucfirst}})
}
func (self *{{o.name}}) Import(data interface{}) {
switch data.(type) {
case {{o.name}}:
{
row := data.({{o.name}})
{%- for f in get_all_fields(o) ~%}
self.{{f.name|ucfirst}} = row.{{f.name|ucfirst}}
{%- endfor ~%}
break
}
default:
break
}
}
func (self *{{o.name}}) Export(data []interface{}) {
{%- for f in get_all_fields(o) ~%}
data[{{loop.index0}}] = self.{{f.name|ucfirst}}
{%- endfor ~%}
}
{% endmacro %}
{% macro decl_enum(o) %}
//==============================
const (
{{_self.enum_consts(o)}}
)
type {{o.name}} int32
var _{{o.name}}_values []int = []int{ {{_self.enum_values_list(o)}} }
var _{{o.name}}_map map[string]{{o.name}}
func init() {
_{{o.name}}_map = map[string]{{o.name}}{ {{_self.enum_values_map(o)}} }
}
func (*{{o.name}}) CLASS_ID() uint32 {
return {{o.classid}}
}
func (*{{o.name}}) CLASS_NAME() string {
return "{{o.name}}"
}
func (*{{o.name}}) DEFAULT_VALUE() int32 {
return {{o.values|first}}
}
func (self *{{o.name}}) IsValid() bool {
return sort.SearchInts(_{{o.name}}_values, int(*self)) != -1
}
func {{o.name}}_GetNameByValue(value int) string {
for name, num := range _{{o.name}}_map {
if value == int(num) {
return name
}
}
return ""
}
func New{{o.name}}ByName(name string) ({{o.name}}, error) {
if v, ok := _{{o.name}}_map[name]; ok == true {
return v, nil
}
return 0, errors.Errorf("Wrong name of {{o.name}}: '%s'", name)
}
{% endmacro %}
{% macro enum_values_list(o) %}
{%- for v in o.values|sort -%}
{{v}},
{%- endfor ~%}
{% endmacro %}
{% macro enum_values_map(o) %}
{%- for k,v in o.values -%}
"{{k}}" : {{v}},
{%- endfor ~%}
{% endmacro %}
{% macro enum_consts(o) %}
{%- for k,v in o.values ~%}
{{o.name}}_{{k}} {{o.name}} = {{v}}
{%- endfor ~%}
{% endmacro %}
{% macro decl_rpc(o) %}
{{_self._decl_rpc_part(o.req, o.code)}}
{{_self._decl_rpc_part(o.rsp, o.code)}}
func New{{o.name}}() *{{o.name}} {
rpc := {{o.name}}{}
rpc.Req = New{{o.req.name}}()
rpc.Rsp = New{{o.rsp.name}}()
return &rpc
}
type {{o.name}} struct {
ErrCode int32
ErrMsg string
Req *{{o.req.name}}
Rsp *{{o.rsp.name}}
}
func (rpc *{{o.name}}) SetError(code int32, msg string) {
rpc.ErrCode = code
rpc.ErrMsg = msg
}
func (rpc *{{o.name}}) GetError() (int32, string) {
return rpc.ErrCode, rpc.ErrMsg
}
func (rpc *{{o.name}}) GetRequest() meta.IMetaStruct {
return rpc.Req
}
func (rpc *{{o.name}}) GetResponse() meta.IMetaStruct {
return rpc.Rsp
}
func (rpc *{{o.name}}) GetName() string {
return "{{o.name}}"
}
func (rpc *{{o.name}}) GetCode() int32 {
return {{o.code}}
}
type IRPCHandler_{{o.name}} interface {
{{o.name}}(*{{o.name}}) error
}
func (rpc *{{o.name}}) Execute(h interface{}) error{
mh, ok := h.(IRPCHandler_{{o.name}})
if !ok {
return errors.New("RPC '{{o.name}}(*{{o.name}}) error' is not implemented")
}
return mh.{{o.name}}(rpc)
}
{% endmacro %}
{% macro _decl_rpc_part(o, code) %}
{{_self.decl_struct(o)}}
var {{o.name}}_ func(interface{}, *{{o.name}}, *{{o.name|rpc_invert}}) error
func (self *{{o.name}}) I{{o.name}}() *{{o.name}} {
return self
}
func (*{{o.name}}) GetCode() int32 {
return {{code}}
}
{% endmacro %}

View File

@ -56,7 +56,7 @@ func (rpc *{{ name }}) WriteResponse(writer meta.Writer) error {
type {{ req_name }} struct {
{%~ for f in r.req.fields %}
{{ f|fname }} {{ f.type|go_type }} `json:"{{ f|alias }}" msgpack:"{{ f|alias }}"`
{{ f|fname }} {{ f.type|go_type(f.tokens) }} `json:"{{ f|alias }}" msgpack:"{{ f|alias }}"`
{%~ endfor %}
}
@ -71,7 +71,7 @@ func New{{ req_name }}() *{{ req_name }} {
type {{ rsp_name }} struct {
{%~ for f in r.rsp.fields %}
{{ f|fname }} {{ f.type|go_type }} `json:"{{ f|alias }}" msgpack:"{{ f|alias }}"`
{{ f|fname }} {{ f.type|go_type(f.tokens) }} `json:"{{ f|alias }}" msgpack:"{{ f|alias }}"`
{%~ endfor %}
}

View File

@ -611,12 +611,16 @@ func (s *{{ name|default(o.name) }}) Reset() {
{% set fname = f|fname %}
{% if f.type is array %}
if s.{{ fname }} == nil {
s.{{ fname }} = make({{ f.type|go_type }}, 0)
s.{{ fname }} = make({{ f.type|go_type(f.tokens) }}, 0)
} else {
s.{{ fname }} = s.{{ fname }}[:0]
}
{% elseif f.type is struct %}
s.{{ fname }}.Reset()
{% if has_token(f, 'virtual') %}
s.{{ fname }} = New{{ f.type|go_type }}()
{% else %}
s.{{ fname }}.Reset()
{% endif %}
{% else %}
s.{{ fname }} = {{ f|default_val }}
{% endif %}
@ -687,14 +691,14 @@ func (s *{{ name|default(s.name) }}) ReadFields(reader meta.Reader) error {
contSize--
}
if !use_mask || (use_mask && s.FieldChanged({{ loop.index0 }})) {
{{ _self.meta_read_field(f.type, 's.' ~ f|fname, f|alias) }}
{{ _self.meta_read_field(f.type, 's.' ~ f|fname, f|alias, f.tokens) }}
{% if has_token(s, 'table') %}
s.changedFields.SetChanged("{{ f|alias }}")
{% endif %}
}
{% else %}
contSize--
{{ _self.meta_read_field(f.type, 's.' ~ f|fname, f|alias) }}
{{ _self.meta_read_field(f.type, 's.' ~ f|fname, f|alias, f.tokens) }}
{% if has_token(s, 'table') %}
s.changedFields.SetChanged("{{ f|alias }}")
{% endif %}
@ -707,7 +711,7 @@ func (s *{{ name|default(s.name) }}) ReadFields(reader meta.Reader) error {
{% endmacro meta_read %}
{% macro meta_read_field(type, fname, alias) %}
{% macro meta_read_field(type, fname, alias, tokens) %}
{% if type is builtin %}
if err := reader.Read{{ type|builtin_type_suffix }}(&{{ fname }}, "{{ alias }}"); err != nil && err != meta.FieldNotFound {
return err
@ -720,6 +724,15 @@ func (s *{{ name|default(s.name) }}) ReadFields(reader meta.Reader) error {
return errors.Errorf("bad enum value `%d` for `{{ alias }}`", {{ fname }})
}
{% elseif type is struct %}
{% if tokens.virtual is defined %}
if v, err := meta.ReadGeneric(reader, CreateReadableById, "{{ alias }}"); err != nil {
if err != meta.FieldNotFound {
return err
}
} else {
{{ fname }} = v.(I{{ type.name }})
}
{% else %}
if err := reader.BeginContainer("{{ alias }}"); err != nil {
if err != meta.FieldNotFound {
return err
@ -732,6 +745,7 @@ func (s *{{ name|default(s.name) }}) ReadFields(reader meta.Reader) error {
return err
}
}
{% endif %}
{% elseif type is array %}
{% set name = fname|split('.')|last %}
{% set size_var = name|lcfirst ~ 'Size' %}
@ -746,8 +760,8 @@ func (s *{{ name|default(s.name) }}) ReadFields(reader meta.Reader) error {
return err
}
for ; {{ size_var }} > 0; {{ size_var }}-- {
var {{ tmp_var }} {{ type.value|go_type }}
{{ _self.meta_read_field(type.value, tmp_var) }}
var {{ tmp_var }} {{ type.value|go_type(tokens) }}
{{ _self.meta_read_field(type.value, tmp_var, '', tokens) }}
{{ fname }} = append({{ fname }}, {{ tmp_var }})
}
if err := reader.EndContainer(); err != nil {
@ -779,15 +793,19 @@ func (s *{{ name|default(o.name) }}) WriteFields(writer meta.Writer) error {
{% endif %}
{% for f in o.fields %}
{{ _self.meta_write_field(f.type, 's.' ~ f|fname, f|alias) }}
{{ _self.meta_write_field(f.type, 's.' ~ f|fname, f|alias, f.tokens) }}
{% endfor %}
return nil
}
func (s *{{ name|default(o.name) }}) FieldsCount() int {
return {{ get_all_fields(o)|length }}
}
{% endmacro meta_write %}
{% macro meta_write_field(type, fname, alias) %}
{% macro meta_write_field(type, fname, alias, tokens) %}
{% if type is builtin %}
if err := writer.Write{{ type|builtin_type_suffix }}({{ fname }}, "{{ alias }}"); err != nil {
return err
@ -797,6 +815,11 @@ func (s *{{ name|default(o.name) }}) WriteFields(writer meta.Writer) error {
return err
}
{% elseif type is struct %}
{% if tokens.virtual is defined %}
if err := meta.WriteGeneric(writer, {{ fname }}, "{{ alias }}"); err != nil {
return err
}
{% else %}
if err := writer.BeginContainer({{ get_all_fields(type)|length }}, "{{ alias }}"); err != nil {
return err
}
@ -806,12 +829,13 @@ func (s *{{ name|default(o.name) }}) WriteFields(writer meta.Writer) error {
if err := writer.EndContainer(); err != nil {
return err
}
{% endif %}
{% elseif type is array %}
if err := writer.BeginCollection(len({{ fname }}), "{{ alias }}"); err != nil {
return err
}
for _, v := range {{ fname }} {
{{ _self.meta_write_field(type.value, 'v') }}
{{ _self.meta_write_field(type.value, 'v', '', tokens) }}
}
if err := writer.EndCollection(); err != nil {
return err
@ -847,7 +871,7 @@ type {{ s.name }} struct {
{% endif %}
{% for f in s.fields %}
{{ f|fname }} {{ f.type|go_type }} `json:"{{ f|alias }},string" msgpack:"{{ f|alias }}"`
{{ f|fname }} {{ f.type|go_type(f.tokens) }} `json:"{{ f|alias }},string" msgpack:"{{ f|alias }}"`
{% endfor %}
{% if has_token(s, 'bitfields') %}
@ -878,7 +902,7 @@ func New{{ name }}() *{{ name }} {
}
type I{{ name }} interface {
meta.Class
meta.Struct
Ptr{{ name }}() *{{ name }}
}
@ -897,6 +921,14 @@ func ({{ name }}) ClassName() string {
func (s *{{ name }}) Ptr{{ name }}() *{{ name }} {
return s
}
func Ptr{{ name }}(s meta.Struct) *{{ name }} {
ptr, ok := s.(I{{ name }})
if !ok {
return nil
}
return ptr.Ptr{{ name }}()
}
{% endmacro struct_methods %}
@ -1083,7 +1115,7 @@ func (s *{{ name|default(s.name) }}) readFieldsAssociative(reader meta.Reader) e
switch field {
{% for f in all_fields %}
case "{{ f|alias }}":
{{ _self.meta_read_field(f.type, 's.' ~ f|fname, 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 #}