github.com/lxt1045/json@v0.0.0-20231013032136-54d6b1d6e525/struct_tag.go (about)

     1  // MIT License
     2  //
     3  // Copyright (c) 2021 Xiantu Li
     4  //
     5  // Permission is hereby granted, free of charge, to any person obtaining a copy
     6  // of this software and associated documentation files (the "Software"), to deal
     7  // in the Software without restriction, including without limitation the rights
     8  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     9  // copies of the Software, and to permit persons to whom the Software is
    10  // furnished to do so, subject to the following conditions:
    11  //
    12  // The above copyright notice and this permission notice shall be included in all
    13  // copies or substantial portions of the Software.
    14  //
    15  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    16  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    17  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    18  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    19  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    20  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    21  // SOFTWARE.
    22  
    23  package json
    24  
    25  import (
    26  	"fmt"
    27  	"reflect"
    28  	"strings"
    29  	"sync"
    30  	"unsafe"
    31  
    32  	lxterrs "github.com/lxt1045/errors"
    33  )
    34  
    35  // TagInfo 拥有tag的struct的成员的解析结果
    36  type TagInfo struct {
    37  	// 常用的放前面,在缓存的概率大
    38  	TagName    string //
    39  	fUnm       unmFunc
    40  	fM         mFunc
    41  	sliceCache *BatchObj
    42  	tireTree   *tireTree
    43  
    44  	BaseType     reflect.Type //
    45  	BaseKind     reflect.Kind // 次成员可能是 **string,[]int 等这种复杂类型,这个 用来指示 "最里层" 的类型
    46  	Offset       uintptr      //偏移量
    47  	TypeSize     int          //
    48  	StringTag    bool         // `json:"field,string"`: 此情形下,需要把struct的int转成json的string
    49  	OmitemptyTag bool         //  `json:"some_field,omitempty"`
    50  
    51  	Children  map[string]*TagInfo // 支持快速获取子节点
    52  	ChildList []*TagInfo          // 支持遍历的顺序;加快遍历速度
    53  
    54  	ptrCacheType reflect.Type // pointer 的 cache
    55  	ptrCache     *BatchObj    // ptrCacheType 类型的 pool
    56  
    57  	slicePoolType       reflect.Type // 除 cdynamicPool 以外的 slice 缓存; slice 动态增长,与 pointer 不一样
    58  	sliceElemGoType     *GoType
    59  	idxSliceObjPool     uintptr
    60  	idxSlicePointerPool uintptr // ptrDeep > 1 时,需要使用
    61  
    62  	SPool  sync.Pool // TODO:slice pool 和 store.pool 放在一起吧,通过 id 来获取获取 pool,并把剩余的”垃圾“放回 sync.Pool 中共下次复用
    63  	SPoolN int32
    64  	SPool2 *BatchObj // 新的 slice cache
    65  
    66  	sPooloffset  int32 // slice pool 在 PoolStore的偏移量; TODO
    67  	psPooloffset int32 // pointer slice pool  在 PoolStore的偏移量
    68  	bsMarshalLen int32 // 缓存上次 生成的 bs 的大小,如果 cache 小于这个值,则丢弃
    69  	bsHaftCount  int32 // 记录上次低于 bsMarshalLen/2 的次数
    70  
    71  }
    72  
    73  const SPoolN = 1024 // * 1024
    74  
    75  func (t *TagInfo) GetChildFromMap(key string) *TagInfo {
    76  	return t.Children[string(key)]
    77  }
    78  
    79  // AddChild 添加下级子节点
    80  func (t *TagInfo) AddChild(c *TagInfo) (err error) {
    81  	if len(t.Children) == 0 {
    82  		t.Children = make(map[string]*TagInfo)
    83  	}
    84  	if _, ok := t.Children[c.TagName]; ok {
    85  		err = fmt.Errorf("error, type[%s].tag[%s]类型配置出错,字段重复", t.TagName, c.TagName)
    86  		return
    87  	}
    88  	t.ChildList = append(t.ChildList, c)
    89  	t.Children[c.TagName] = c
    90  	return
    91  }
    92  
    93  // []byte 是一种特殊的底层数据类型,需要 base64 编码
    94  func isBytes(typ reflect.Type) bool {
    95  	bsType := reflect.TypeOf(&[]byte{})
    96  	return UnpackType(bsType).Hash == UnpackType(typ).Hash
    97  }
    98  func isStrings(typ reflect.Type) bool {
    99  	bsType := reflect.TypeOf([]string{})
   100  	return UnpackType(bsType).Hash == UnpackType(typ).Hash
   101  }
   102  
   103  type ancestor struct {
   104  	hash uint32
   105  	tag  *TagInfo
   106  }
   107  
   108  func (ti *TagInfo) setFuncs(ptrBuilder, sliceBuilder *TypeBuilder, typ reflect.Type, anonymous bool, ancestors []ancestor) (son *TagInfo, err error) {
   109  	son = ti
   110  	ptrDeep, baseType := 0, typ
   111  	var pidx *uintptr
   112  	for ; ; typ = typ.Elem() {
   113  		if typ.Kind() == reflect.Ptr {
   114  			ptrDeep++
   115  			continue
   116  		}
   117  		baseType = typ
   118  		break
   119  	}
   120  	son.BaseType = baseType
   121  	if ptrDeep > 0 {
   122  		pidx = &[]uintptr{0}[0]
   123  		ptrBuilder.AppendTagField(baseType, pidx)
   124  	}
   125  
   126  	// 先从最后一个基础类型开始处理
   127  	switch baseType.Kind() {
   128  	case reflect.Bool:
   129  		ti.fUnm, ti.fM = boolMFuncs(pidx)
   130  	case reflect.Uint, reflect.Uint64, reflect.Uintptr:
   131  		ti.fUnm, ti.fM = uint64MFuncs(pidx)
   132  	case reflect.Int, reflect.Int64:
   133  		ti.fUnm, ti.fM = int64MFuncs(pidx)
   134  	case reflect.Uint32:
   135  		ti.fUnm, ti.fM = uint32MFuncs(pidx)
   136  	case reflect.Int32:
   137  		ti.fUnm, ti.fM = int32MFuncs(pidx)
   138  	case reflect.Uint16:
   139  		ti.fUnm, ti.fM = uint16MFuncs(pidx)
   140  	case reflect.Int16:
   141  		ti.fUnm, ti.fM = int16MFuncs(pidx)
   142  	case reflect.Uint8:
   143  		ti.fUnm, ti.fM = uint8MFuncs(pidx)
   144  	case reflect.Int8:
   145  		ti.fUnm, ti.fM = int8MFuncs(pidx)
   146  	case reflect.Float64:
   147  		ti.fUnm, ti.fM = float64MFuncs(pidx)
   148  	case reflect.Float32:
   149  		ti.fUnm, ti.fM = float32MFuncs(pidx)
   150  	case reflect.String:
   151  		ti.fUnm, ti.fM = stringMFuncs(pidx)
   152  	case reflect.Slice: // &[]byte; Array
   153  		if isBytes(baseType) {
   154  			ti.fUnm, ti.fM = bytesMFuncs(pidx)
   155  		} else {
   156  			ti.BaseType = baseType
   157  			sliceType := baseType.Elem()
   158  			ti.sliceElemGoType = UnpackType(sliceType)
   159  			sliceBuilder.AppendTagField(ti.BaseType, &ti.idxSliceObjPool)
   160  			if ptrDeep > 0 {
   161  				typ := reflect.TypeOf([]unsafe.Pointer{})
   162  				sliceBuilder.AppendTagField(typ, &ti.idxSlicePointerPool)
   163  			}
   164  			if isStrings(baseType) {
   165  				// 字符串数组
   166  				ti.fUnm, ti.fM = sliceStringsMFuncs()
   167  				// ti.fUnm, ti.fM = sliceMFuncs(pidx)
   168  			} else if ptrDeep > 0 {
   169  				//指针数组
   170  				ti.fUnm, ti.fM = sliceNoscanMFuncs(pidx)
   171  			} else if UnpackType(sliceType).Hash == UnpackType(reflect.TypeOf(int(0))).Hash && ptrDeep == 0 {
   172  				// int 数组
   173  				ti.fUnm, ti.fM = sliceIntsMFuncs(pidx)
   174  				// ti.fUnm, ti.fM = sliceNoscanMFuncs(pidx)
   175  			} else if UnpackType(sliceType).PtrData == 0 && ptrDeep == 0 {
   176  				ti.fUnm, ti.fM = sliceNoscanMFuncs(pidx)
   177  			} else if UnpackType(sliceType).Hash == UnpackType(reflect.TypeOf(interface{}(0))).Hash && ptrDeep == 0 {
   178  				// interface{} 数组
   179  				ti.fUnm, ti.fM = sliceMFuncs(pidx)
   180  			} else {
   181  				ti.fUnm, ti.fM = sliceMFuncs(pidx)
   182  			}
   183  			son = &TagInfo{
   184  				TagName:  `"son"`,
   185  				BaseType: sliceType,
   186  				TypeSize: int(sliceType.Size()),
   187  			}
   188  
   189  			subSon, err := son.setFuncs(ptrBuilder, sliceBuilder, sliceType, false /*anonymous*/, ancestors)
   190  			if err != nil {
   191  				return nil, lxterrs.Wrap(err, "Struct")
   192  			}
   193  			subSon.sliceCache = NewBatchObj(sliceType)
   194  
   195  			err = ti.AddChild(subSon) //TODO: err = ti.AddChild(son) ?
   196  			// err = ti.AddChild(son)
   197  			if err != nil {
   198  				return nil, lxterrs.Wrap(err, "Struct")
   199  			}
   200  
   201  			ti.SPoolN = (1 << 20) / int32(ti.BaseType.Size())
   202  			ti.SPool.New = func() any {
   203  				v := reflect.MakeSlice(ti.BaseType, 0, int(ti.SPoolN)) // SPoolN)
   204  				p := reflectValueToPointer(&v)
   205  				pH := (*SliceHeader)(p)
   206  				pH.Cap = pH.Cap * int(sliceType.Size())
   207  				return (*[]uint8)(p)
   208  			}
   209  			ti.SPool2 = NewBatchObj(subSon.BaseType)
   210  		}
   211  	case reflect.Struct:
   212  		var sonIdx uintptr = 0
   213  		ti.fUnm, ti.fM = structMFuncs(pidx, &sonIdx)
   214  
   215  		son, err = NewStructTagInfo(baseType, ancestors)
   216  		// goType := UnpackType(baseType)
   217  		// son, err = LoadTagNodeByType(baseType, goType.Hash)
   218  		if err != nil {
   219  			return nil, lxterrs.Wrap(err, "Struct")
   220  		}
   221  		son.fUnm, son.fM = ti.fUnm, ti.fM
   222  		if son != nil && son.ptrCacheType != nil {
   223  			ptrBuilder.AppendTagField(son.ptrCacheType, &sonIdx) //TODO: 如果是 slice 这里需要处理成 slice 模式
   224  		}
   225  		if son == nil {
   226  			// TODO: fUnm中需要重建 store.pool,并从
   227  			// tag, err := LoadTagNode(vi, goType.Hash) 获取 tag,需要延后处理?
   228  			ti.fUnm, ti.fM = structMFuncs(pidx, &sonIdx)
   229  		}
   230  		// 匿名成员的处理; 这里只能处理费指针嵌入,指针嵌入逻辑在上一层
   231  		if !anonymous {
   232  			if son.slicePoolType != nil {
   233  				sliceBuilder.AppendTagField(son.slicePoolType, &ti.idxSliceObjPool)
   234  				// ti.slicePool.New = son.slicePool.New
   235  				// ti.slicePoolType = son.slicePoolType
   236  				// ti.ptrCache = son.ptrCache
   237  				// ti.ptrCacheType = son.ptrCacheType
   238  			}
   239  			for _, c := range son.ChildList {
   240  				err = ti.AddChild(c)
   241  				if err != nil {
   242  					return nil, lxterrs.Wrap(err, "AddChild")
   243  				}
   244  			}
   245  			// ti.buildChildMap()
   246  		} else {
   247  			for _, c := range son.ChildList {
   248  				if ptrDeep == 0 {
   249  					c.Offset += ti.Offset
   250  				} else {
   251  					fUnm, fM := c.fUnm, c.fM
   252  					c.fM = func(store Store, in []byte) (out []byte) {
   253  						store.obj = *(*unsafe.Pointer)(store.obj)
   254  						if store.obj != nil {
   255  							return fM(store, in)
   256  						}
   257  						out = append(in, "null"...)
   258  						return
   259  					}
   260  					c.fUnm = func(idxSlash int, store PoolStore, stream string) (i, iSlash int) {
   261  						store.obj = *(*unsafe.Pointer)(store.obj)
   262  						if store.obj == nil {
   263  							store.obj = store.Idx(*pidx)
   264  						}
   265  						return fUnm(idxSlash, store, stream)
   266  					}
   267  				}
   268  				err = ti.AddChild(c)
   269  				if err != nil {
   270  					return nil, lxterrs.Wrap(err, "AddChild")
   271  				}
   272  			}
   273  		}
   274  	case reflect.Interface:
   275  		// Interface 需要根据实际类型创建
   276  		ti.fUnm, ti.fM = interfaceMFuncs(pidx)
   277  
   278  	case reflect.Map:
   279  		ti.fUnm, ti.fM = mapMFuncs(pidx)
   280  		valueType := baseType.Elem()
   281  		son = &TagInfo{
   282  			TagName:  `"son"`,
   283  			TypeSize: int(valueType.Size()), // TODO
   284  			// Builder:  ti.Builder,
   285  		}
   286  		err = ti.AddChild(son)
   287  		if err != nil {
   288  			return nil, lxterrs.Wrap(err, "Struct")
   289  		}
   290  		subSon, err := son.setFuncs(ptrBuilder, sliceBuilder, valueType, false /*anonymous*/, ancestors)
   291  		if err != nil {
   292  			return nil, lxterrs.Wrap(err, "Struct")
   293  		}
   294  		_ = subSon
   295  	default:
   296  		return nil, lxterrs.New("errors type:%s", baseType)
   297  	}
   298  
   299  	// 处理一下指针
   300  	for i := 1; i < ptrDeep; i++ {
   301  		var idxP *uintptr = &[]uintptr{0}[0]
   302  		ptrBuilder.AppendPointer(fmt.Sprintf("%s_%d", ti.TagName, i), idxP)
   303  		fUnm, fM := ti.fUnm, ti.fM
   304  		ti.fUnm = func(idxSlash int, store PoolStore, stream string) (i, iSlash int) {
   305  			store.obj = store.Idx(*idxP)
   306  			return fUnm(idxSlash, store, stream)
   307  		}
   308  		ti.fM = func(store Store, in []byte) (out []byte) {
   309  			store.obj = *(*unsafe.Pointer)(store.obj)
   310  			return fM(store, in)
   311  		}
   312  	}
   313  
   314  	return
   315  }
   316  
   317  //NewStructTagInfo 解析struct的tag字段,并返回解析的结果
   318  /*
   319     每个 struct 都搞一个 pointerCacheType,在使用的时候直接获取; 再搞一个 slicePool 在是 slice 时使用;
   320     二者不会同一时刻出现,是不是可以合并为同一个值?
   321  */
   322  func NewStructTagInfo(typIn reflect.Type, ancestors []ancestor) (ti *TagInfo, err error) {
   323  	if typIn.Kind() != reflect.Struct {
   324  		err = lxterrs.New("NewStructTagInfo only accepts structs; got %v", typIn.Kind())
   325  		return
   326  	}
   327  
   328  	ptrBuilder := NewTypeBuilder()
   329  	sliceBuilder := NewTypeBuilder()
   330  	ti = &TagInfo{
   331  		BaseType: typIn,
   332  		TagName:  typIn.String(),
   333  		BaseKind: typIn.Kind(), // 解析出最内层类型
   334  		TypeSize: int(typIn.Size()),
   335  	}
   336  
   337  	// 通过 ancestors 避免死循环
   338  	goType := UnpackType(typIn)
   339  	isNestedLoop := false // 是否嵌套循环
   340  	for _, a := range ancestors {
   341  		if a.hash == goType.Hash {
   342  			ti = nil // 以返回 nil 来处理后续逻辑
   343  
   344  			// TODO: 暂时不支持嵌套循环类型
   345  			panic("Nested loops are not yet supported")
   346  			return // 避免嵌套循环
   347  			isNestedLoop = true
   348  			_ = isNestedLoop
   349  			break
   350  			/*
   351  				// TODO: 针对循环类型
   352  				// fUnm 和 fM 里重新创建缓存和对象,再获取 tag 继续往下执行
   353  				store := PoolStore{
   354  					tag:         tag,
   355  					obj:         prv.ptr, // eface.Value,
   356  					pointerPool: tag.ptrCache.Get(),
   357  				}
   358  				//slice 才需要的缓存
   359  				if tag.slicePool.New != nil {
   360  					store.slicePool = tag.slicePool.Get().(unsafe.Pointer)
   361  					store.dynPool = dynPool.Get().(*dynamicPool)
   362  
   363  					err = parseRoot(bs[i:], store)
   364  
   365  					tag.slicePool.Put(store.slicePool)
   366  					dynPool.Put(store.dynPool)
   367  				} else {
   368  					err = parseRoot(bs[i:], store)
   369  				}
   370  			*/
   371  		}
   372  	}
   373  	ancestors = append(ancestors, ancestor{goType.Hash, ti})
   374  
   375  	// 解析 struct 成员类型
   376  	for i := 0; i < typIn.NumField(); i++ {
   377  		field := typIn.Field(i)
   378  		son := &TagInfo{
   379  			BaseType: field.Type,
   380  			Offset:   field.Offset,
   381  			BaseKind: field.Type.Kind(),
   382  			TypeSize: int(field.Type.Size()),
   383  			TagName:  field.Name,
   384  			// TagName:  `"` + field.Name + `"`,
   385  		}
   386  
   387  		if !field.IsExported() {
   388  			continue // 非导出成员不处理
   389  		}
   390  		fieldTag := newtag(field.Tag.Get("json")) //从tag列表中取出下标为i的tag //json:"field,string"
   391  		if fieldTag.negligible() {
   392  			continue
   393  		}
   394  		if !fieldTag.empty() {
   395  			son.TagName, son.StringTag, son.OmitemptyTag = fieldTag.parse()
   396  		}
   397  
   398  		// 最复杂的一部分,处理不同类型的 Handler
   399  		_, err = son.setFuncs(ptrBuilder, sliceBuilder, field.Type, field.Anonymous, ancestors)
   400  		if err != nil {
   401  			err = lxterrs.Wrap(err, "son.setFuncs")
   402  			return
   403  		}
   404  		if !field.Anonymous {
   405  			if len(son.ChildList) > 0 {
   406  				son.tireTree, err = NewTireTree(son.ChildList)
   407  				if err != nil {
   408  					return
   409  				}
   410  			}
   411  			err = ti.AddChild(son)
   412  			if err != nil {
   413  				return
   414  			}
   415  		} else {
   416  			// 如果是匿名成员类型,需要将其子成员插入为父节点的子成员;
   417  			// 此外,get set 函数也要做相应修改
   418  			for _, c := range son.ChildList {
   419  				err = ti.AddChild(c)
   420  				if err != nil {
   421  					return
   422  				}
   423  			}
   424  		}
   425  	}
   426  	if len(ti.ChildList) > 0 {
   427  		ti.tireTree, err = NewTireTree(ti.ChildList)
   428  		if err != nil {
   429  			return
   430  		}
   431  	}
   432  
   433  	// 缓存处理
   434  	if len(ptrBuilder.fields) > 0 {
   435  		ti.ptrCacheType = ptrBuilder.Build()
   436  		ti.ptrCache = NewBatchObj(ti.ptrCacheType)
   437  	}
   438  
   439  	ti.slicePoolType = sliceBuilder.Build()
   440  
   441  	return
   442  }
   443  
   444  type tag string
   445  
   446  func newtag(tagv string) tag {
   447  	tagv = strings.TrimSpace(tagv)
   448  	return tag(tagv)
   449  }
   450  
   451  // 应该忽视的
   452  func (t tag) negligible() bool {
   453  	if t == "-" {
   454  		return true
   455  	}
   456  	return false
   457  }
   458  
   459  func (t tag) empty() bool {
   460  	if t == "" {
   461  		return true
   462  	}
   463  	return false
   464  }
   465  
   466  func (t tag) parse() (name string, bString, bOmitempty bool) {
   467  	tvs := strings.Split(string(t), ",")
   468  	// name = `"` + strings.TrimSpace(tvs[0]) + `"` // 此处加上 双引号 是为了方便使用 改进后的 hash map
   469  	name = strings.TrimSpace(tvs[0]) // 此处加上 双引号 是为了方便使用 改进后的 hash map
   470  
   471  	for i := 1; i < len(tvs); i++ {
   472  		v := strings.TrimSpace(tvs[i])
   473  		if v == "string" {
   474  			bString = true
   475  			continue
   476  		}
   477  		if v == "omitempty" {
   478  			bOmitempty = true
   479  			continue
   480  		}
   481  	}
   482  	return
   483  }