github.com/cloudwego/kitex@v0.9.0/pkg/generic/thrift/parse.go (about)

     1  /*
     2   * Copyright 2021 CloudWeGo Authors
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package thrift
    18  
    19  import (
    20  	"context"
    21  	"errors"
    22  	"fmt"
    23  	"runtime/debug"
    24  
    25  	"github.com/cloudwego/thriftgo/parser"
    26  	"github.com/cloudwego/thriftgo/semantic"
    27  
    28  	"github.com/cloudwego/kitex/pkg/generic/descriptor"
    29  	"github.com/cloudwego/kitex/pkg/gofunc"
    30  	"github.com/cloudwego/kitex/pkg/klog"
    31  )
    32  
    33  const (
    34  	initRecursionDepth = 0
    35  )
    36  
    37  // ParseMode .
    38  type ParseMode int
    39  
    40  const (
    41  	// LastServiceOnly forces the parser to parse only the last service definition.
    42  	LastServiceOnly ParseMode = iota
    43  
    44  	// FirstServiceOnly forces the parser to parse only the first service definition.
    45  	FirstServiceOnly
    46  
    47  	// CombineServices forces the parser to combine methods of all service definitions.
    48  	// Note that method names of the service definitions can not be duplicate.
    49  	CombineServices
    50  )
    51  
    52  var defaultParseMode = LastServiceOnly
    53  
    54  // DefaultParseMode returns the default parse mode.
    55  func DefaultParseMode() ParseMode {
    56  	return defaultParseMode
    57  }
    58  
    59  // SetDefaultParseMode sets the default parse mode.
    60  func SetDefaultParseMode(m ParseMode) {
    61  	defaultParseMode = m
    62  }
    63  
    64  // Parse descriptor from parser.Thrift
    65  func Parse(tree *parser.Thrift, mode ParseMode) (*descriptor.ServiceDescriptor, error) {
    66  	if len(tree.Services) == 0 {
    67  		return nil, errors.New("empty serverce from idls")
    68  	}
    69  	if err := semantic.ResolveSymbols(tree); err != nil {
    70  		return nil, err
    71  	}
    72  
    73  	sDsc := &descriptor.ServiceDescriptor{
    74  		Functions: map[string]*descriptor.FunctionDescriptor{},
    75  		Router:    descriptor.NewRouter(),
    76  	}
    77  
    78  	// support one service
    79  	svcs := tree.Services
    80  	switch mode {
    81  	case LastServiceOnly:
    82  		svcs = svcs[len(svcs)-1:]
    83  		sDsc.Name = svcs[len(svcs)-1].Name
    84  	case FirstServiceOnly:
    85  		svcs = svcs[:1]
    86  		sDsc.Name = svcs[0].Name
    87  	case CombineServices:
    88  		sDsc.Name = "CombinedServices"
    89  	}
    90  
    91  	visitedSvcs := make(map[*parser.Service]bool, len(tree.Services))
    92  	for _, svc := range svcs {
    93  		for p := range getAllSvcs(svc, tree, visitedSvcs) {
    94  			svc := p.data.(*parser.Service)
    95  			structsCache := map[string]*descriptor.TypeDescriptor{}
    96  			for _, fn := range svc.Functions {
    97  				if err := addFunction(fn, p.tree, sDsc, structsCache); err != nil {
    98  					return nil, err
    99  				}
   100  			}
   101  		}
   102  	}
   103  	return sDsc, nil
   104  }
   105  
   106  type pair struct {
   107  	tree *parser.Thrift
   108  	data interface{}
   109  }
   110  
   111  func getAllSvcs(svc *parser.Service, tree *parser.Thrift, visitedSvcs map[*parser.Service]bool) chan *pair {
   112  	svcs := make(chan *pair)
   113  	addSvc := func(tree *parser.Thrift, svc *parser.Service) {
   114  		if exist := visitedSvcs[svc]; !exist {
   115  			svcs <- &pair{tree: tree, data: svc}
   116  			visitedSvcs[svc] = true
   117  		}
   118  	}
   119  	gofunc.GoFunc(context.Background(), func() {
   120  		addSvc(tree, svc)
   121  		for base := svc.Extends; base != ""; base = svc.Extends {
   122  			ref := svc.GetReference()
   123  			if ref != nil {
   124  				idx := ref.GetIndex()
   125  				base = ref.GetName()
   126  				tree = tree.Includes[idx].Reference
   127  			}
   128  			svc, _ = tree.GetService(base)
   129  			addSvc(tree, svc)
   130  		}
   131  		close(svcs)
   132  	})
   133  	return svcs
   134  }
   135  
   136  func addFunction(fn *parser.Function, tree *parser.Thrift, sDsc *descriptor.ServiceDescriptor, structsCache map[string]*descriptor.TypeDescriptor) (err error) {
   137  	if sDsc.Functions[fn.Name] != nil {
   138  		return fmt.Errorf("duplicate method name: %s", fn.Name)
   139  	}
   140  	if len(fn.Arguments) == 0 {
   141  		return fmt.Errorf("empty arguments in function: %s", fn.Name)
   142  	}
   143  	// only support single argument
   144  	field := fn.Arguments[0]
   145  	req := &descriptor.TypeDescriptor{
   146  		Type: descriptor.STRUCT,
   147  		Struct: &descriptor.StructDescriptor{
   148  			FieldsByID:   map[int32]*descriptor.FieldDescriptor{},
   149  			FieldsByName: map[string]*descriptor.FieldDescriptor{},
   150  		},
   151  	}
   152  	var reqType *descriptor.TypeDescriptor
   153  	reqType, err = parseType(field.Type, tree, structsCache, initRecursionDepth)
   154  	if err != nil {
   155  		return err
   156  	}
   157  	hasRequestBase := false
   158  	if reqType.Type == descriptor.STRUCT {
   159  		for _, f := range reqType.Struct.FieldsByName {
   160  			if f.Type.IsRequestBase {
   161  				hasRequestBase = true
   162  				break
   163  			}
   164  		}
   165  	}
   166  	reqField := &descriptor.FieldDescriptor{
   167  		Name: field.Name,
   168  		ID:   field.ID,
   169  		Type: reqType,
   170  	}
   171  	req.Struct.FieldsByID[field.ID] = reqField
   172  	req.Struct.FieldsByName[field.Name] = reqField
   173  	// parse response filed
   174  	resp := &descriptor.TypeDescriptor{
   175  		Type: descriptor.STRUCT,
   176  		Struct: &descriptor.StructDescriptor{
   177  			FieldsByID:   map[int32]*descriptor.FieldDescriptor{},
   178  			FieldsByName: map[string]*descriptor.FieldDescriptor{},
   179  		},
   180  	}
   181  	var respType *descriptor.TypeDescriptor
   182  	respType, err = parseType(fn.FunctionType, tree, structsCache, initRecursionDepth)
   183  	if err != nil {
   184  		return err
   185  	}
   186  	respField := &descriptor.FieldDescriptor{
   187  		Type: respType,
   188  	}
   189  	// response has no name or id
   190  	resp.Struct.FieldsByID[0] = respField
   191  	resp.Struct.FieldsByName[""] = respField
   192  
   193  	if len(fn.Throws) > 0 {
   194  		// only support single exception
   195  		field := fn.Throws[0]
   196  		var exceptionType *descriptor.TypeDescriptor
   197  		exceptionType, err = parseType(field.Type, tree, structsCache, initRecursionDepth)
   198  		if err != nil {
   199  			return err
   200  		}
   201  		exceptionField := &descriptor.FieldDescriptor{
   202  			Name:        field.Name,
   203  			ID:          field.ID,
   204  			IsException: true,
   205  			Type:        exceptionType,
   206  		}
   207  		resp.Struct.FieldsByID[field.ID] = exceptionField
   208  		resp.Struct.FieldsByName[field.Name] = exceptionField
   209  	}
   210  	fnDsc := &descriptor.FunctionDescriptor{
   211  		Name:           fn.Name,
   212  		Oneway:         fn.Oneway,
   213  		Request:        req,
   214  		Response:       resp,
   215  		HasRequestBase: hasRequestBase,
   216  	}
   217  	defer func() {
   218  		if ret := recover(); ret != nil {
   219  			klog.Errorf("KITEX: router handle failed, err=%v\nstack=%s", ret, string(debug.Stack()))
   220  			err = fmt.Errorf("router handle failed, err=%v", ret)
   221  		}
   222  	}()
   223  	for _, ann := range fn.Annotations {
   224  		for _, v := range ann.GetValues() {
   225  			if handle, ok := descriptor.FindAnnotation(ann.GetKey(), v); ok {
   226  				if nr, ok := handle.(descriptor.NewRoute); ok {
   227  					sDsc.Router.Handle(nr(v, fnDsc))
   228  					break
   229  				}
   230  			}
   231  		}
   232  	}
   233  	sDsc.Functions[fn.Name] = fnDsc
   234  	return nil
   235  }
   236  
   237  // reuse builtin types
   238  var builtinTypes = map[string]*descriptor.TypeDescriptor{
   239  	"void":   {Name: "void", Type: descriptor.VOID, Struct: new(descriptor.StructDescriptor)},
   240  	"bool":   {Name: "bool", Type: descriptor.BOOL},
   241  	"byte":   {Name: "byte", Type: descriptor.BYTE},
   242  	"i8":     {Name: "i8", Type: descriptor.I08},
   243  	"i16":    {Name: "i16", Type: descriptor.I16},
   244  	"i32":    {Name: "i32", Type: descriptor.I32},
   245  	"i64":    {Name: "i64", Type: descriptor.I64},
   246  	"double": {Name: "double", Type: descriptor.DOUBLE},
   247  	"string": {Name: "string", Type: descriptor.STRING},
   248  	"binary": {Name: "binary", Type: descriptor.STRING},
   249  }
   250  
   251  // arg cache:
   252  // only support self reference on the same file
   253  // cross file self reference complicate matters
   254  func parseType(t *parser.Type, tree *parser.Thrift, cache map[string]*descriptor.TypeDescriptor, recursionDepth int) (*descriptor.TypeDescriptor, error) {
   255  	if ty, ok := builtinTypes[t.Name]; ok {
   256  		return ty, nil
   257  	}
   258  
   259  	nextRecursionDepth := recursionDepth + 1
   260  
   261  	var err error
   262  	switch t.Name {
   263  	case "list":
   264  		ty := &descriptor.TypeDescriptor{Name: t.Name}
   265  		ty.Type = descriptor.LIST
   266  		ty.Elem, err = parseType(t.ValueType, tree, cache, nextRecursionDepth)
   267  		return ty, err
   268  	case "set":
   269  		ty := &descriptor.TypeDescriptor{Name: t.Name}
   270  		ty.Type = descriptor.SET
   271  		ty.Elem, err = parseType(t.ValueType, tree, cache, nextRecursionDepth)
   272  		return ty, err
   273  	case "map":
   274  		ty := &descriptor.TypeDescriptor{Name: t.Name}
   275  		ty.Type = descriptor.MAP
   276  		if ty.Key, err = parseType(t.KeyType, tree, cache, nextRecursionDepth); err != nil {
   277  			return nil, err
   278  		}
   279  		ty.Elem, err = parseType(t.ValueType, tree, cache, nextRecursionDepth)
   280  		return ty, err
   281  	default:
   282  		// check the cache
   283  		if ty, ok := cache[t.Name]; ok {
   284  			return ty, nil
   285  		}
   286  		typePkg, typeName := splitType(t.Name)
   287  		if typePkg != "" {
   288  			ref, ok := tree.GetReference(typePkg)
   289  			if !ok {
   290  				return nil, fmt.Errorf("miss reference: %s", typePkg)
   291  			}
   292  			tree = ref
   293  			// cross file reference need empty cache
   294  			cache = map[string]*descriptor.TypeDescriptor{}
   295  		}
   296  		if typDef, ok := tree.GetTypedef(typeName); ok {
   297  			return parseType(typDef.Type, tree, cache, nextRecursionDepth)
   298  		}
   299  		if _, ok := tree.GetEnum(typeName); ok {
   300  			return builtinTypes["i32"], nil
   301  		}
   302  		var st *parser.StructLike
   303  		var ok bool
   304  		st, ok = tree.GetUnion(typeName)
   305  		if !ok {
   306  			st, ok = tree.GetStruct(typeName)
   307  		}
   308  		if !ok {
   309  			st, ok = tree.GetException(typeName)
   310  		}
   311  		if !ok {
   312  			return nil, fmt.Errorf("missing type: %s", typeName)
   313  		}
   314  		ty := &descriptor.TypeDescriptor{
   315  			Name: t.Name,
   316  			Type: descriptor.STRUCT,
   317  			Struct: &descriptor.StructDescriptor{
   318  				Name:           typeName,
   319  				FieldsByID:     map[int32]*descriptor.FieldDescriptor{},
   320  				FieldsByName:   map[string]*descriptor.FieldDescriptor{},
   321  				RequiredFields: map[int32]*descriptor.FieldDescriptor{},
   322  				DefaultFields:  map[string]*descriptor.FieldDescriptor{},
   323  			},
   324  			// the first depth of base.Base is Request Base
   325  			IsRequestBase: t.Name == "base.Base" && recursionDepth == 1,
   326  		}
   327  		// cannot cache the request base
   328  		if !ty.IsRequestBase {
   329  			cache[t.Name] = ty
   330  		}
   331  		for _, field := range st.Fields {
   332  			_f := &descriptor.FieldDescriptor{
   333  				ID:       field.ID,
   334  				Name:     field.Name,
   335  				Required: field.Requiredness == parser.FieldType_Required,
   336  				Optional: field.Requiredness == parser.FieldType_Optional,
   337  			}
   338  
   339  			for _, ann := range field.Annotations {
   340  				for _, v := range ann.GetValues() {
   341  					if handle, ok := descriptor.FindAnnotation(ann.GetKey(), v); ok {
   342  						switch h := handle.(type) {
   343  						case descriptor.NewHTTPMapping:
   344  							_f.HTTPMapping = h(v)
   345  						case descriptor.NewValueMapping:
   346  							_f.ValueMapping = h(v)
   347  						case descriptor.NewFieldMapping:
   348  							// execute at compile time
   349  							h(v).Handle(_f)
   350  						case nil:
   351  							// none annotation
   352  						default:
   353  							// not supported annotation type
   354  							return nil, fmt.Errorf("not supported handle type: %T", handle)
   355  						}
   356  					}
   357  				}
   358  			}
   359  			if _f.HTTPMapping == nil {
   360  				_f.HTTPMapping = descriptor.DefaultNewMapping(_f.FieldName())
   361  			}
   362  			if _f.Type, err = parseType(field.Type, tree, cache, nextRecursionDepth); err != nil {
   363  				return nil, err
   364  			}
   365  			// set default value
   366  			if field.IsSetDefault() {
   367  				_f.DefaultValue, err = parse(tree, field.Name, field.Type, field.Default)
   368  				if err != nil {
   369  					return nil, err
   370  				}
   371  				ty.Struct.DefaultFields[_f.FieldName()] = _f
   372  			}
   373  			ty.Struct.FieldsByID[field.ID] = _f
   374  			ty.Struct.FieldsByName[_f.FieldName()] = _f
   375  			if _f.Required {
   376  				ty.Struct.RequiredFields[field.ID] = _f
   377  			}
   378  		}
   379  		return ty, nil
   380  	}
   381  }
   382  
   383  func parse(tree *parser.Thrift, name string, t *parser.Type, v *parser.ConstValue) (interface{}, error) {
   384  	switch t.Category {
   385  	case parser.Category_Bool:
   386  		return onBool(tree, name, t, v)
   387  	case parser.Category_Byte:
   388  		val, err := onInt(tree, name, t, v)
   389  		if err != nil {
   390  			return nil, err
   391  		}
   392  		return byte(val), nil
   393  	case parser.Category_I16:
   394  		val, err := onInt(tree, name, t, v)
   395  		if err != nil {
   396  			return nil, err
   397  		}
   398  		return int16(val), nil
   399  	case parser.Category_I32:
   400  		val, err := onInt(tree, name, t, v)
   401  		if err != nil {
   402  			return nil, err
   403  		}
   404  		return int32(val), nil
   405  	case parser.Category_I64:
   406  		return onInt(tree, name, t, v)
   407  	case parser.Category_Double:
   408  		return onDouble(tree, name, t, v)
   409  	case parser.Category_String:
   410  		return onStr(tree, name, t, v)
   411  	case parser.Category_Binary:
   412  		str, err := onStr(tree, name, t, v)
   413  		if err != nil {
   414  			return nil, err
   415  		}
   416  		return []byte(str), nil
   417  	case parser.Category_Enum:
   418  		return onEnum(tree, name, t, v)
   419  	case parser.Category_Set, parser.Category_List:
   420  		return onSetOrList(tree, name, t, v)
   421  	case parser.Category_Map:
   422  		return onMap(tree, name, t, v)
   423  	case parser.Category_Struct, parser.Category_Union, parser.Category_Exception:
   424  		return onStructLike(tree, name, t, v)
   425  	}
   426  	return nil, fmt.Errorf("type error: '%s' was declared as type %s but got value[%v] of category[%s]", name, t, v, t.Category)
   427  }
   428  
   429  func onBool(tree *parser.Thrift, name string, t *parser.Type, v *parser.ConstValue) (bool, error) {
   430  	switch v.Type {
   431  	case parser.ConstType_ConstInt:
   432  		val := v.TypedValue.GetInt()
   433  		return val > 0, nil
   434  	case parser.ConstType_ConstDouble:
   435  		val := v.TypedValue.GetDouble()
   436  		return val > 0, nil
   437  	case parser.ConstType_ConstIdentifier:
   438  		s := v.TypedValue.GetIdentifier()
   439  		if s == "true" {
   440  			return true, nil
   441  		}
   442  		if s == "false" {
   443  			return false, nil
   444  		}
   445  		val, err := getIDValue(tree, name, t, v.Extra)
   446  		if err != nil {
   447  			return false, err
   448  		}
   449  		switch rv := val.(type) {
   450  		case bool:
   451  			return rv, nil
   452  		}
   453  		return false, fmt.Errorf("%s[%T] not match bool type", v.Extra.Name, val)
   454  	}
   455  	return false, fmt.Errorf("type error: '%s' was declared as type %s", name, t)
   456  }
   457  
   458  func onInt(tree *parser.Thrift, name string, t *parser.Type, v *parser.ConstValue) (int64, error) {
   459  	switch v.Type {
   460  	case parser.ConstType_ConstInt:
   461  		val := v.TypedValue.GetInt()
   462  		return val, nil
   463  	case parser.ConstType_ConstIdentifier:
   464  		s := v.TypedValue.GetIdentifier()
   465  		if s == "true" {
   466  			return 1, nil
   467  		}
   468  		if s == "false" {
   469  			return 0, nil
   470  		}
   471  		val, err := getIDValue(tree, name, t, v.Extra)
   472  		if err != nil {
   473  			return 0, err
   474  		}
   475  		switch rv := val.(type) {
   476  		case byte:
   477  			return int64(rv), nil
   478  		case int16:
   479  			return int64(rv), nil
   480  		case int32:
   481  			return int64(rv), nil
   482  		case int64:
   483  			return rv, nil
   484  		}
   485  		return 0, fmt.Errorf("%s[%T] not match int64 type", v.Extra.Name, val)
   486  	}
   487  	return 0, fmt.Errorf("type error: '%s' was declared as type %s", name, t)
   488  }
   489  
   490  func onDouble(tree *parser.Thrift, name string, t *parser.Type, v *parser.ConstValue) (float64, error) {
   491  	switch v.Type {
   492  	case parser.ConstType_ConstInt:
   493  		val := v.TypedValue.GetInt()
   494  		return float64(val), nil
   495  	case parser.ConstType_ConstDouble:
   496  		val := v.TypedValue.GetDouble()
   497  		return val, nil
   498  	case parser.ConstType_ConstIdentifier:
   499  		s := v.TypedValue.GetIdentifier()
   500  		if s == "true" {
   501  			return 1.0, nil
   502  		}
   503  		if s == "false" {
   504  			return 0.0, nil
   505  		}
   506  		val, err := getIDValue(tree, name, t, v.Extra)
   507  		if err != nil {
   508  			return 0, err
   509  		}
   510  		switch rv := val.(type) {
   511  		case float64:
   512  			return rv, nil
   513  		case int64:
   514  			return float64(rv), nil
   515  		}
   516  		return 0, fmt.Errorf("%s[%T] not match float64 type", v.Extra.Name, val)
   517  	}
   518  	return 0, fmt.Errorf("type error: '%s' was declared as type %s", name, t)
   519  }
   520  
   521  func onStr(tree *parser.Thrift, name string, t *parser.Type, v *parser.ConstValue) (string, error) {
   522  	switch v.Type {
   523  	case parser.ConstType_ConstLiteral:
   524  		return v.TypedValue.GetLiteral(), nil
   525  	case parser.ConstType_ConstIdentifier:
   526  		s := v.TypedValue.GetIdentifier()
   527  		if s == "true" || s == "false" {
   528  			break
   529  		}
   530  		val, err := getIDValue(tree, name, t, v.Extra)
   531  		if err != nil {
   532  			return "", err
   533  		}
   534  		switch rv := val.(type) {
   535  		case string:
   536  			return rv, nil
   537  		}
   538  		return "", fmt.Errorf("%s[%T] not match string type", v.Extra.Name, val)
   539  	}
   540  	return "", fmt.Errorf("type error: '%s' was declared as type %s", name, t)
   541  }
   542  
   543  func onEnum(tree *parser.Thrift, name string, t *parser.Type, v *parser.ConstValue) (int64, error) {
   544  	switch v.Type {
   545  	case parser.ConstType_ConstInt:
   546  		return v.TypedValue.GetInt(), nil
   547  	case parser.ConstType_ConstIdentifier:
   548  		val, err := getIDValue(tree, name, t, v.Extra)
   549  		if err != nil {
   550  			return 0, err
   551  		}
   552  		switch rv := val.(type) {
   553  		case int64:
   554  			return rv, nil
   555  		}
   556  		return 0, fmt.Errorf("%s[%T] not match int64 type", v.Extra.Name, val)
   557  	}
   558  	return 0, fmt.Errorf("expect const value for %q is a int or enum, got %+v", name, v)
   559  }
   560  
   561  func onSetOrList(tree *parser.Thrift, name string, t *parser.Type, v *parser.ConstValue) (res []interface{}, err error) {
   562  	switch v.Type {
   563  	case parser.ConstType_ConstList:
   564  		elemName := "element of " + name
   565  		for _, elem := range v.TypedValue.GetList() {
   566  			val, err := parse(tree, elemName, t.ValueType, elem)
   567  			if err != nil {
   568  				return nil, err
   569  			}
   570  			res = append(res, val)
   571  		}
   572  		return res, nil
   573  	case parser.ConstType_ConstIdentifier:
   574  		val, err := getIDValue(tree, name, t, v.Extra)
   575  		if err != nil {
   576  			return nil, err
   577  		}
   578  		switch rv := val.(type) {
   579  		case []interface{}:
   580  			return rv, nil
   581  		}
   582  		return nil, fmt.Errorf("%s[%T] not match []interface{} type", v.Extra.Name, val)
   583  	}
   584  	// fault tolerance
   585  	return
   586  }
   587  
   588  func onMap(tree *parser.Thrift, name string, t *parser.Type, v *parser.ConstValue) (res map[interface{}]interface{}, err error) {
   589  	res = make(map[interface{}]interface{})
   590  	switch v.Type {
   591  	case parser.ConstType_ConstMap:
   592  		for _, mcv := range v.TypedValue.Map {
   593  			keyName := "key of " + name
   594  			key, err := parse(tree, keyName, bin2str(t.KeyType), mcv.Key)
   595  			if err != nil {
   596  				return nil, err
   597  			}
   598  			valName := "value of " + name
   599  			val, err := parse(tree, valName, t.ValueType, mcv.Value)
   600  			if err != nil {
   601  				return nil, err
   602  			}
   603  			res[key] = val
   604  		}
   605  		return res, nil
   606  
   607  	case parser.ConstType_ConstIdentifier:
   608  		val, err := getIDValue(tree, name, t, v.Extra)
   609  		if err != nil {
   610  			return nil, err
   611  		}
   612  		switch rv := val.(type) {
   613  		case map[interface{}]interface{}:
   614  			return rv, nil
   615  		}
   616  		return nil, fmt.Errorf("%s[%T] not match map[interface{}]interface{} type", v.Extra.Name, val)
   617  	}
   618  	// fault tolerance
   619  	return
   620  }
   621  
   622  func onStructLike(tree *parser.Thrift, name string, t *parser.Type, v *parser.ConstValue) (res map[string]interface{}, err error) {
   623  	if v.Type == parser.ConstType_ConstIdentifier {
   624  		val, err := getIDValue(tree, name, t, v.Extra)
   625  		if err != nil {
   626  			return nil, err
   627  		}
   628  		switch rv := val.(type) {
   629  		case map[string]interface{}:
   630  			return rv, nil
   631  		}
   632  		return nil, fmt.Errorf("%s[%T] not match map[string]interface{} type", v.Extra.Name, val)
   633  	}
   634  
   635  	if v.Type != parser.ConstType_ConstMap {
   636  		// constant value of a struct-like must be a map literal
   637  		return nil, fmt.Errorf("type error: '%s' was declared as type %s", name, t)
   638  	}
   639  
   640  	// get the target struct-like with typedef dereferenced
   641  	file, st, err := getStructLike(tree, t)
   642  	if err != nil {
   643  		return nil, err
   644  	}
   645  
   646  	res = make(map[string]interface{})
   647  	for _, mcv := range v.TypedValue.Map {
   648  		if mcv.Key.Type != parser.ConstType_ConstLiteral {
   649  			return nil, fmt.Errorf("expect literals as keys in default value of struct type '%s', got '%s'", name, mcv.Key.Type)
   650  		}
   651  		n := mcv.Key.TypedValue.GetLiteral()
   652  
   653  		f, ok := st.GetField(n)
   654  		if !ok {
   655  			return nil, fmt.Errorf("field %q not found in %q (%q): %v",
   656  				n, st.Name, file.Filename, v,
   657  			)
   658  		}
   659  		val, err := parse(file, st.Name+"."+f.Name, f.Type, mcv.Value)
   660  		if err != nil {
   661  			return nil, err
   662  		}
   663  		res[n] = val
   664  	}
   665  
   666  	return res, nil
   667  }
   668  
   669  func getStructLike(tree *parser.Thrift, t *parser.Type) (ast *parser.Thrift, s *parser.StructLike, err error) {
   670  	var x *parser.Type
   671  	ast, x, err = semantic.Deref(tree, t)
   672  	if err != nil {
   673  		err = fmt.Errorf("expect %q a typedef or struct-like in %q: %w",
   674  			t.Name, tree.Filename, err)
   675  		return nil, nil, err
   676  	}
   677  	for _, y := range ast.GetStructLikes() {
   678  		if x.Name == y.Name {
   679  			s = y
   680  		}
   681  	}
   682  	if s == nil {
   683  		err = fmt.Errorf("expect %q a struct-like in %q: not found: %v",
   684  			x.Name, ast.Filename, x == t)
   685  		return nil, nil, err
   686  	}
   687  	return
   688  }
   689  
   690  func getIDValue(tree *parser.Thrift, name string, t *parser.Type, extra *parser.ConstValueExtra) (interface{}, error) {
   691  	if extra.Index == -1 {
   692  		if extra.IsEnum {
   693  			enum, ok := tree.GetEnum(extra.Sel)
   694  			if !ok {
   695  				return nil, fmt.Errorf("no matching enum of %s", extra.Sel)
   696  			}
   697  			for _, v := range enum.Values {
   698  				if v.Name == extra.Name {
   699  					return v.Value, nil
   700  				}
   701  			}
   702  		} else {
   703  			if con, ok := tree.GetConstant(extra.Name); ok {
   704  				return parse(tree, name, con.Type, con.Value)
   705  			}
   706  		}
   707  	} else {
   708  		tree = tree.Includes[extra.Index].Reference
   709  		extra = &parser.ConstValueExtra{
   710  			Index:  -1,
   711  			IsEnum: extra.IsEnum,
   712  			Name:   extra.Name,
   713  			Sel:    extra.Sel,
   714  		}
   715  		return getIDValue(tree, name, t, extra)
   716  	}
   717  	return nil, fmt.Errorf("undefined value %s", extra.Name)
   718  }
   719  
   720  func bin2str(t *parser.Type) *parser.Type {
   721  	if t.Category == parser.Category_Binary {
   722  		r := *t
   723  		r.Category = parser.Category_String
   724  		return &r
   725  	}
   726  	return t
   727  }