github.com/niubaoshu/gotiny@v0.0.4-0.20211018120156-10d393f19ad0/decEngine.go (about)

     1  package gotiny
     2  
     3  import (
     4  	"reflect"
     5  	"sync"
     6  	"time"
     7  	"unsafe"
     8  )
     9  
    10  type decEng func(*Decoder, unsafe.Pointer) // 解码器
    11  
    12  var (
    13  	rt2decEng = map[reflect.Type]decEng{
    14  		reflect.TypeOf((*bool)(nil)).Elem():           decBool,
    15  		reflect.TypeOf((*int)(nil)).Elem():            decInt,
    16  		reflect.TypeOf((*int8)(nil)).Elem():           decInt8,
    17  		reflect.TypeOf((*int16)(nil)).Elem():          decInt16,
    18  		reflect.TypeOf((*int32)(nil)).Elem():          decInt32,
    19  		reflect.TypeOf((*int64)(nil)).Elem():          decInt64,
    20  		reflect.TypeOf((*uint)(nil)).Elem():           decUint,
    21  		reflect.TypeOf((*uint8)(nil)).Elem():          decUint8,
    22  		reflect.TypeOf((*uint16)(nil)).Elem():         decUint16,
    23  		reflect.TypeOf((*uint32)(nil)).Elem():         decUint32,
    24  		reflect.TypeOf((*uint64)(nil)).Elem():         decUint64,
    25  		reflect.TypeOf((*uintptr)(nil)).Elem():        decUintptr,
    26  		reflect.TypeOf((*unsafe.Pointer)(nil)).Elem(): decPointer,
    27  		reflect.TypeOf((*float32)(nil)).Elem():        decFloat32,
    28  		reflect.TypeOf((*float64)(nil)).Elem():        decFloat64,
    29  		reflect.TypeOf((*complex64)(nil)).Elem():      decComplex64,
    30  		reflect.TypeOf((*complex128)(nil)).Elem():     decComplex128,
    31  		reflect.TypeOf((*[]byte)(nil)).Elem():         decBytes,
    32  		reflect.TypeOf((*string)(nil)).Elem():         decString,
    33  		reflect.TypeOf((*time.Time)(nil)).Elem():      decTime,
    34  		reflect.TypeOf((*struct{})(nil)).Elem():       decIgnore,
    35  		reflect.TypeOf(nil):                           decIgnore,
    36  	}
    37  
    38  	baseDecEngines = []decEng{
    39  		reflect.Invalid:       decIgnore,
    40  		reflect.Bool:          decBool,
    41  		reflect.Int:           decInt,
    42  		reflect.Int8:          decInt8,
    43  		reflect.Int16:         decInt16,
    44  		reflect.Int32:         decInt32,
    45  		reflect.Int64:         decInt64,
    46  		reflect.Uint:          decUint,
    47  		reflect.Uint8:         decUint8,
    48  		reflect.Uint16:        decUint16,
    49  		reflect.Uint32:        decUint32,
    50  		reflect.Uint64:        decUint64,
    51  		reflect.Uintptr:       decUintptr,
    52  		reflect.UnsafePointer: decPointer,
    53  		reflect.Float32:       decFloat32,
    54  		reflect.Float64:       decFloat64,
    55  		reflect.Complex64:     decComplex64,
    56  		reflect.Complex128:    decComplex128,
    57  		reflect.String:        decString,
    58  	}
    59  	decLock sync.RWMutex
    60  )
    61  
    62  func getDecEngine(rt reflect.Type) decEng {
    63  	decLock.RLock()
    64  	engine := rt2decEng[rt]
    65  	decLock.RUnlock()
    66  	if engine != nil {
    67  		return engine
    68  	}
    69  	decLock.Lock()
    70  	buildDecEngine(rt, &engine)
    71  	decLock.Unlock()
    72  	return engine
    73  }
    74  
    75  func buildDecEngine(rt reflect.Type, engPtr *decEng) {
    76  	engine, has := rt2decEng[rt]
    77  	if has {
    78  		*engPtr = engine
    79  		return
    80  	}
    81  
    82  	if _, engine = implementOtherSerializer(rt); engine != nil {
    83  		rt2decEng[rt] = engine
    84  		*engPtr = engine
    85  		return
    86  	}
    87  
    88  	kind := rt.Kind()
    89  	var eEng decEng
    90  	switch kind {
    91  	case reflect.Ptr:
    92  		et := rt.Elem()
    93  		defer buildDecEngine(et, &eEng)
    94  		engine = func(d *Decoder, p unsafe.Pointer) {
    95  			if d.decIsNotNil() {
    96  				if isNil(p) {
    97  					*(*unsafe.Pointer)(p) = unsafe.Pointer(reflect.New(et).Elem().UnsafeAddr())
    98  				}
    99  				eEng(d, *(*unsafe.Pointer)(p))
   100  			} else if !isNil(p) {
   101  				*(*unsafe.Pointer)(p) = nil
   102  			}
   103  		}
   104  	case reflect.Array:
   105  		l, et := rt.Len(), rt.Elem()
   106  		size := et.Size()
   107  		defer buildDecEngine(et, &eEng)
   108  		engine = func(d *Decoder, p unsafe.Pointer) {
   109  			for i := 0; i < l; i++ {
   110  				eEng(d, unsafe.Pointer(uintptr(p)+uintptr(i)*size))
   111  			}
   112  		}
   113  	case reflect.Slice:
   114  		et := rt.Elem()
   115  		size := et.Size()
   116  		defer buildDecEngine(et, &eEng)
   117  		engine = func(d *Decoder, p unsafe.Pointer) {
   118  			header := (*reflect.SliceHeader)(p)
   119  			if d.decIsNotNil() {
   120  				l := d.decLength()
   121  				if isNil(p) || header.Cap < l {
   122  					*header = reflect.SliceHeader{Data: reflect.MakeSlice(rt, l, l).Pointer(), Len: l, Cap: l}
   123  				} else {
   124  					header.Len = l
   125  				}
   126  				for i := 0; i < l; i++ {
   127  					eEng(d, unsafe.Pointer(header.Data+uintptr(i)*size))
   128  				}
   129  			} else if !isNil(p) {
   130  				*header = reflect.SliceHeader{}
   131  			}
   132  		}
   133  	case reflect.Map:
   134  		kt, vt := rt.Key(), rt.Elem()
   135  		skt, svt := reflect.SliceOf(kt), reflect.SliceOf(vt)
   136  		var kEng, vEng decEng
   137  		defer buildDecEngine(kt, &kEng)
   138  		defer buildDecEngine(vt, &vEng)
   139  		engine = func(d *Decoder, p unsafe.Pointer) {
   140  			if d.decIsNotNil() {
   141  				l := d.decLength()
   142  				var v reflect.Value
   143  				if isNil(p) {
   144  					v = reflect.MakeMapWithSize(rt, l)
   145  					*(*unsafe.Pointer)(p) = unsafe.Pointer(v.Pointer())
   146  				} else {
   147  					v = reflect.NewAt(rt, p).Elem()
   148  				}
   149  				keys, vals := reflect.MakeSlice(skt, l, l), reflect.MakeSlice(svt, l, l)
   150  				for i := 0; i < l; i++ {
   151  					key, val := keys.Index(i), vals.Index(i)
   152  					kEng(d, unsafe.Pointer(key.UnsafeAddr()))
   153  					vEng(d, unsafe.Pointer(val.UnsafeAddr()))
   154  					v.SetMapIndex(key, val)
   155  				}
   156  			} else if !isNil(p) {
   157  				*(*unsafe.Pointer)(p) = nil
   158  			}
   159  		}
   160  	case reflect.Struct:
   161  		fields, offs := getFieldType(rt, 0)
   162  		nf := len(fields)
   163  		fEngines := make([]decEng, nf)
   164  		defer func() {
   165  			for i := 0; i < nf; i++ {
   166  				buildDecEngine(fields[i], &fEngines[i])
   167  			}
   168  		}()
   169  		engine = func(d *Decoder, p unsafe.Pointer) {
   170  			for i := 0; i < len(fEngines) && i < len(offs); i++ {
   171  				fEngines[i](d, unsafe.Pointer(uintptr(p)+offs[i]))
   172  			}
   173  		}
   174  	case reflect.Interface:
   175  		engine = func(d *Decoder, p unsafe.Pointer) {
   176  			if d.decIsNotNil() {
   177  				name := ""
   178  				decString(d, unsafe.Pointer(&name))
   179  				et, has := name2type[name]
   180  				if !has {
   181  					panic("unknown typ:" + name)
   182  				}
   183  				v := reflect.NewAt(rt, p).Elem()
   184  				var ev reflect.Value
   185  				if v.IsNil() || v.Elem().Type() != et {
   186  					ev = reflect.New(et).Elem()
   187  				} else {
   188  					ev = v.Elem()
   189  				}
   190  				getDecEngine(et)(d, getUnsafePointer(&ev))
   191  				v.Set(ev)
   192  			} else if !isNil(p) {
   193  				*(*unsafe.Pointer)(p) = nil
   194  			}
   195  		}
   196  	case reflect.Chan, reflect.Func:
   197  		panic("not support " + rt.String() + " type")
   198  	default:
   199  		engine = baseDecEngines[kind]
   200  	}
   201  	rt2decEng[rt] = engine
   202  	*engPtr = engine
   203  }