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

     1  package gotiny
     2  
     3  import (
     4  	"reflect"
     5  	"sync"
     6  	"time"
     7  	"unsafe"
     8  )
     9  
    10  type encEng func(*Encoder, unsafe.Pointer) //编码器
    11  
    12  var (
    13  	rt2encEng = map[reflect.Type]encEng{
    14  		reflect.TypeOf((*bool)(nil)).Elem():           encBool,
    15  		reflect.TypeOf((*int)(nil)).Elem():            encInt,
    16  		reflect.TypeOf((*int8)(nil)).Elem():           encInt8,
    17  		reflect.TypeOf((*int16)(nil)).Elem():          encInt16,
    18  		reflect.TypeOf((*int32)(nil)).Elem():          encInt32,
    19  		reflect.TypeOf((*int64)(nil)).Elem():          encInt64,
    20  		reflect.TypeOf((*uint)(nil)).Elem():           encUint,
    21  		reflect.TypeOf((*uint8)(nil)).Elem():          encUint8,
    22  		reflect.TypeOf((*uint16)(nil)).Elem():         encUint16,
    23  		reflect.TypeOf((*uint32)(nil)).Elem():         encUint32,
    24  		reflect.TypeOf((*uint64)(nil)).Elem():         encUint64,
    25  		reflect.TypeOf((*uintptr)(nil)).Elem():        encUintptr,
    26  		reflect.TypeOf((*unsafe.Pointer)(nil)).Elem(): encPointer,
    27  		reflect.TypeOf((*float32)(nil)).Elem():        encFloat32,
    28  		reflect.TypeOf((*float64)(nil)).Elem():        encFloat64,
    29  		reflect.TypeOf((*complex64)(nil)).Elem():      encComplex64,
    30  		reflect.TypeOf((*complex128)(nil)).Elem():     encComplex128,
    31  		reflect.TypeOf((*[]byte)(nil)).Elem():         encBytes,
    32  		reflect.TypeOf((*string)(nil)).Elem():         encString,
    33  		reflect.TypeOf((*time.Time)(nil)).Elem():      encTime,
    34  		reflect.TypeOf((*struct{})(nil)).Elem():       encIgnore,
    35  		reflect.TypeOf(nil):                           encIgnore,
    36  	}
    37  
    38  	encEngines = [...]encEng{
    39  		reflect.Invalid:       encIgnore,
    40  		reflect.Bool:          encBool,
    41  		reflect.Int:           encInt,
    42  		reflect.Int8:          encInt8,
    43  		reflect.Int16:         encInt16,
    44  		reflect.Int32:         encInt32,
    45  		reflect.Int64:         encInt64,
    46  		reflect.Uint:          encUint,
    47  		reflect.Uint8:         encUint8,
    48  		reflect.Uint16:        encUint16,
    49  		reflect.Uint32:        encUint32,
    50  		reflect.Uint64:        encUint64,
    51  		reflect.Uintptr:       encUintptr,
    52  		reflect.UnsafePointer: encPointer,
    53  		reflect.Float32:       encFloat32,
    54  		reflect.Float64:       encFloat64,
    55  		reflect.Complex64:     encComplex64,
    56  		reflect.Complex128:    encComplex128,
    57  		reflect.String:        encString,
    58  	}
    59  
    60  	encLock sync.RWMutex
    61  )
    62  
    63  func UnusedUnixNanoEncodeTimeType() {
    64  	delete(rt2encEng, reflect.TypeOf((*time.Time)(nil)).Elem())
    65  	delete(rt2decEng, reflect.TypeOf((*time.Time)(nil)).Elem())
    66  }
    67  
    68  func getEncEngine(rt reflect.Type) encEng {
    69  	encLock.RLock()
    70  	engine := rt2encEng[rt]
    71  	encLock.RUnlock()
    72  	if engine != nil {
    73  		return engine
    74  	}
    75  	encLock.Lock()
    76  	buildEncEngine(rt, &engine)
    77  	encLock.Unlock()
    78  	return engine
    79  }
    80  
    81  func buildEncEngine(rt reflect.Type, engPtr *encEng) {
    82  	engine := rt2encEng[rt]
    83  	if engine != nil {
    84  		*engPtr = engine
    85  		return
    86  	}
    87  
    88  	if engine, _ = implementOtherSerializer(rt); engine != nil {
    89  		rt2encEng[rt] = engine
    90  		*engPtr = engine
    91  		return
    92  	}
    93  
    94  	kind := rt.Kind()
    95  	var eEng encEng
    96  	switch kind {
    97  	case reflect.Ptr:
    98  		defer buildEncEngine(rt.Elem(), &eEng)
    99  		engine = func(e *Encoder, p unsafe.Pointer) {
   100  			isNotNil := !isNil(p)
   101  			e.encIsNotNil(isNotNil)
   102  			if isNotNil {
   103  				eEng(e, *(*unsafe.Pointer)(p))
   104  			}
   105  		}
   106  	case reflect.Array:
   107  		et, l := rt.Elem(), rt.Len()
   108  		defer buildEncEngine(et, &eEng)
   109  		size := et.Size()
   110  		engine = func(e *Encoder, p unsafe.Pointer) {
   111  			for i := 0; i < l; i++ {
   112  				eEng(e, unsafe.Pointer(uintptr(p)+uintptr(i)*size))
   113  			}
   114  		}
   115  	case reflect.Slice:
   116  		et := rt.Elem()
   117  		size := et.Size()
   118  		defer buildEncEngine(et, &eEng)
   119  		engine = func(e *Encoder, p unsafe.Pointer) {
   120  			isNotNil := !isNil(p)
   121  			e.encIsNotNil(isNotNil)
   122  			if isNotNil {
   123  				header := (*reflect.SliceHeader)(p)
   124  				l := header.Len
   125  				e.encLength(l)
   126  				for i := 0; i < l; i++ {
   127  					eEng(e, unsafe.Pointer(header.Data+uintptr(i)*size))
   128  				}
   129  			}
   130  		}
   131  	case reflect.Map:
   132  		var kEng encEng
   133  		defer buildEncEngine(rt.Key(), &kEng)
   134  		defer buildEncEngine(rt.Elem(), &eEng)
   135  		engine = func(e *Encoder, p unsafe.Pointer) {
   136  			isNotNil := !isNil(p)
   137  			e.encIsNotNil(isNotNil)
   138  			if isNotNil {
   139  				v := reflect.NewAt(rt, p).Elem()
   140  				e.encLength(v.Len())
   141  				keys := v.MapKeys()
   142  				for i := 0; i < len(keys); i++ {
   143  					val := v.MapIndex(keys[i])
   144  					kEng(e, getUnsafePointer(&keys[i]))
   145  					eEng(e, getUnsafePointer(&val))
   146  				}
   147  			}
   148  		}
   149  	case reflect.Struct:
   150  		fields, offs := getFieldType(rt, 0)
   151  		nf := len(fields)
   152  		fEngines := make([]encEng, nf)
   153  		defer func() {
   154  			for i := 0; i < nf; i++ {
   155  				buildEncEngine(fields[i], &fEngines[i])
   156  			}
   157  		}()
   158  		engine = func(e *Encoder, p unsafe.Pointer) {
   159  			for i := 0; i < len(fEngines) && i < len(offs); i++ {
   160  				fEngines[i](e, unsafe.Pointer(uintptr(p)+offs[i]))
   161  			}
   162  		}
   163  	case reflect.Interface:
   164  		if rt.NumMethod() > 0 {
   165  			engine = func(e *Encoder, p unsafe.Pointer) {
   166  				isNotNil := !isNil(p)
   167  				e.encIsNotNil(isNotNil)
   168  				if isNotNil {
   169  					v := reflect.ValueOf(*(*interface {
   170  						M()
   171  					})(p))
   172  					et := v.Type()
   173  					e.encString(getNameOfType(et))
   174  					getEncEngine(et)(e, getUnsafePointer(&v))
   175  				}
   176  			}
   177  		} else {
   178  			engine = func(e *Encoder, p unsafe.Pointer) {
   179  				isNotNil := !isNil(p)
   180  				e.encIsNotNil(isNotNil)
   181  				if isNotNil {
   182  					v := reflect.ValueOf(*(*interface{})(p))
   183  					et := v.Type()
   184  					e.encString(getNameOfType(et))
   185  					getEncEngine(et)(e, getUnsafePointer(&v))
   186  				}
   187  			}
   188  		}
   189  	case reflect.Chan, reflect.Func:
   190  		panic("not support " + rt.String() + " type")
   191  	default:
   192  		engine = encEngines[kind]
   193  	}
   194  	rt2encEng[rt] = engine
   195  	*engPtr = engine
   196  }