github.com/profzone/eden-framework@v1.0.10/pkg/courier/transport_http/transform/utils.go (about)

     1  package transform
     2  
     3  import (
     4  	"encoding"
     5  	"encoding/json"
     6  	"reflect"
     7  	"strconv"
     8  	"strings"
     9  
    10  	"github.com/sirupsen/logrus"
    11  
    12  	"github.com/profzone/eden-framework/pkg/env"
    13  	"github.com/profzone/eden-framework/pkg/reflectx"
    14  	"github.com/profzone/eden-framework/pkg/strings"
    15  )
    16  
    17  type TagFlags map[string]bool
    18  
    19  func GetTagValueAndFlags(tagString string) (v string, tagFlags TagFlags) {
    20  	valueAndFlags := strings.Split(tagString, ",")
    21  	v = valueAndFlags[0]
    22  	tagFlags = TagFlags{}
    23  	if len(valueAndFlags) > 1 {
    24  		for _, flag := range valueAndFlags[1:] {
    25  			tagFlags[flag] = true
    26  		}
    27  	}
    28  	return
    29  }
    30  
    31  func GetStructFieldDisplayName(field *reflect.StructField) string {
    32  	if jsonName, exists, _ := GetTagJSON(field); exists && jsonName != "" {
    33  		return jsonName
    34  	}
    35  	return field.Name
    36  }
    37  
    38  func GetParameterDisplayName(field *reflect.StructField) (string, TagFlags) {
    39  	if fieldName, exists, flags := GetTagName(field); exists && fieldName != "" {
    40  		return fieldName, flags
    41  	}
    42  	if jsonName, exists, flags := GetTagJSON(field); exists && jsonName != "" {
    43  		if !env.IsOnline() {
    44  			//logrus.Warnf("%s `%s`, deprecated `json` tag for naming parameter, please use `name` tag instead", field.Name, field.Tag)
    45  		}
    46  		return jsonName, flags
    47  	}
    48  	return field.Name, TagFlags{}
    49  }
    50  
    51  func GetTagJSON(field *reflect.StructField) (name string, exists bool, tagFlags TagFlags) {
    52  	name, exists = field.Tag.Lookup("json")
    53  	if exists {
    54  		name, tagFlags = GetTagValueAndFlags(name)
    55  	}
    56  	return
    57  }
    58  
    59  func GetTagName(field *reflect.StructField) (name string, exists bool, tagFlags TagFlags) {
    60  	name, exists = field.Tag.Lookup("name")
    61  	if exists {
    62  		name, tagFlags = GetTagValueAndFlags(name)
    63  	}
    64  	return
    65  }
    66  
    67  func GetTagStyle(field *reflect.StructField) (name string, exists bool, tagFlags TagFlags) {
    68  	name, exists = field.Tag.Lookup("style")
    69  	if exists {
    70  		name, tagFlags = GetTagValueAndFlags(name)
    71  	}
    72  	return
    73  }
    74  
    75  func GetTagFmt(field *reflect.StructField) (name string, exists bool, tagFlags TagFlags) {
    76  	name, exists = field.Tag.Lookup("fmt")
    77  	if exists {
    78  		name, tagFlags = GetTagValueAndFlags(name)
    79  	}
    80  	return
    81  }
    82  
    83  func GetTagDefault(field *reflect.StructField) (string, bool) {
    84  	return field.Tag.Lookup("default")
    85  }
    86  
    87  func GetTagValidate(field *reflect.StructField) (string, bool) {
    88  	return field.Tag.Lookup("validate")
    89  }
    90  
    91  func GetTagErrMsg(field *reflect.StructField) (string, bool) {
    92  	return field.Tag.Lookup("errMsg")
    93  }
    94  
    95  func GetTagIn(field *reflect.StructField) (tagIn string, hasIn bool, tagInFlags map[string]bool) {
    96  	tagIn, hasIn = field.Tag.Lookup("in")
    97  	if hasIn {
    98  		tagIn, tagInFlags = GetTagValueAndFlags(tagIn)
    99  	}
   100  	return
   101  }
   102  
   103  func MustStructValue(functionName string, rv reflect.Value) {
   104  	if rv.Kind() != reflect.Struct {
   105  		logrus.Panicf("%s args must a struct value, but got %+v %+v", functionName, rv.Type(), rv.Interface())
   106  	}
   107  }
   108  
   109  func Stringify(v interface{}) ([]byte, error) {
   110  	if marshaler, ok := v.(json.Marshaler); ok {
   111  		return Unquote(marshaler.MarshalJSON())
   112  	}
   113  	if textMarshaler, ok := v.(encoding.TextMarshaler); ok {
   114  		return textMarshaler.MarshalText()
   115  	}
   116  	s, err := str.ConvertToStr(v)
   117  	if err != nil {
   118  		return nil, err
   119  	}
   120  	return []byte(s), nil
   121  }
   122  
   123  func Unquote(data []byte, err error) ([]byte, error) {
   124  	if err != nil {
   125  		return nil, err
   126  	}
   127  	if len(data) > 2 {
   128  		if string(data[0]) == `"` && string(data[len(data)-1]) == `"` {
   129  			return data[1 : len(data)-1], nil
   130  		}
   131  	}
   132  	return data, err
   133  }
   134  
   135  func ResolveCommaSplitValues(tpe reflect.Type, ss ...string) (values []string) {
   136  	tpe = reflectx.IndirectType(tpe)
   137  	if tpe.Kind() == reflect.Slice || tpe.Kind() == reflect.Array {
   138  		itemTpe := reflectx.IndirectType(tpe.Elem())
   139  		if !(itemTpe.Kind() == reflect.Struct || itemTpe.Kind() == reflect.Map) {
   140  			for _, s := range ss {
   141  				values = append(values, strings.Split(s, ",")...)
   142  			}
   143  			return
   144  		}
   145  	}
   146  	return ss
   147  }
   148  
   149  func LocateJSONPath(data []byte, offset int64) string {
   150  	i := 0
   151  	arrayPaths := map[string]bool{}
   152  	arrayIdxSet := map[string]int{}
   153  	pathWalker := &PathWalker{}
   154  
   155  	markObjectKey := func() {
   156  		jsonKey, l := nextString(data[i:])
   157  		i += l
   158  
   159  		if i < int(offset) && len(jsonKey) > 0 {
   160  			key, _ := strconv.Unquote(string(jsonKey))
   161  			pathWalker.Enter(key)
   162  		}
   163  	}
   164  
   165  	markArrayIdx := func(path string) {
   166  		if arrayPaths[path] {
   167  			arrayIdxSet[path]++
   168  		} else {
   169  			arrayPaths[path] = true
   170  		}
   171  		pathWalker.Enter(arrayIdxSet[path])
   172  	}
   173  
   174  	for i < int(offset) {
   175  		i += nextToken(data[i:])
   176  		char := data[i]
   177  
   178  		switch char {
   179  		case '"':
   180  			_, l := nextString(data[i:])
   181  			i += l
   182  		case '[', '{':
   183  			i++
   184  
   185  			if char == '[' {
   186  				markArrayIdx(pathWalker.String())
   187  			} else {
   188  				markObjectKey()
   189  			}
   190  		case '}', ']', ',':
   191  			i++
   192  			pathWalker.Exit()
   193  
   194  			if char == ',' {
   195  				path := pathWalker.String()
   196  
   197  				if _, ok := arrayPaths[path]; ok {
   198  					markArrayIdx(path)
   199  				} else {
   200  					markObjectKey()
   201  				}
   202  			}
   203  		default:
   204  			i++
   205  		}
   206  	}
   207  
   208  	return pathWalker.String()
   209  }
   210  
   211  func nextToken(data []byte) int {
   212  	for i, c := range data {
   213  		switch c {
   214  		case ' ', '\n', '\r', '\t':
   215  			continue
   216  		default:
   217  			return i
   218  		}
   219  	}
   220  	return -1
   221  }
   222  
   223  func nextString(data []byte) (finalData []byte, l int) {
   224  	quoteStartAt := -1
   225  	for i, c := range data {
   226  		switch c {
   227  		case '"':
   228  			if i > 0 && string(data[i-1]) == "\\" {
   229  				continue
   230  			}
   231  			if quoteStartAt >= 0 {
   232  				return data[quoteStartAt : i+1], i + 1
   233  			} else {
   234  				quoteStartAt = i
   235  			}
   236  		default:
   237  			continue
   238  		}
   239  	}
   240  	return nil, 0
   241  }