gitee.com/quant1x/gox@v1.21.2/encoding/binary/cstruct/properties.go (about)

     1  package cstruct
     2  
     3  import (
     4  	"reflect"
     5  	"sync"
     6  )
     7  
     8  // StructProperties
     9  
    10  type StructProperties struct {
    11  	Prop      []*Properties
    12  	fixedSize int
    13  }
    14  
    15  var (
    16  	propertiesMu  sync.RWMutex
    17  	propertiesMap = make(map[reflect.Type]*StructProperties)
    18  )
    19  
    20  func GetProperties(t reflect.Type) *StructProperties {
    21  	if t.Kind() != reflect.Struct {
    22  		panic("cstruct: type must have kind cstruct")
    23  	}
    24  
    25  	propertiesMu.RLock()
    26  	sprop, ok := propertiesMap[t]
    27  	propertiesMu.RUnlock()
    28  	if ok {
    29  		return sprop
    30  	}
    31  
    32  	propertiesMu.Lock()
    33  	defer propertiesMu.Unlock()
    34  	sprop = getPropertiesLocked(t)
    35  	return sprop
    36  }
    37  
    38  func getPropertiesLocked(t reflect.Type) *StructProperties {
    39  	if prop, ok := propertiesMap[t]; ok {
    40  		return prop
    41  	}
    42  
    43  	prop := new(StructProperties)
    44  	propertiesMap[t] = prop
    45  	prop.Prop = make([]*Properties, t.NumField())
    46  	for i := 0; i < t.NumField(); i++ {
    47  		f := t.Field(i)
    48  		p := new(Properties)
    49  		name := f.Name
    50  		p.init(f.Type, name, "", &f, &prop.fixedSize)
    51  		prop.Prop[i] = p
    52  	}
    53  
    54  	return prop
    55  }
    56  
    57  // Properties
    58  
    59  type encoder func(p *Buffer, prop *Properties, base structPointer) error
    60  type decoder func(p *Buffer, prop *Properties, base structPointer) error
    61  type sizer func(p *Buffer, prop *Properties, base structPointer) int
    62  
    63  type Properties struct {
    64  	Name  string
    65  	field field
    66  	enc   encoder
    67  	dec   decoder
    68  	siz   sizer
    69  	t     reflect.Type
    70  	stype reflect.Type
    71  	sprop *StructProperties
    72  }
    73  
    74  func (p *Properties) init(typ reflect.Type, name, tag string, f *reflect.StructField, fixedSize *int) {
    75  	p.Name = name
    76  	if f != nil {
    77  		p.field = toField(f)
    78  	}
    79  	p.setEncAndDec(typ, f, fixedSize)
    80  }
    81  
    82  func (p *Properties) setEncAndDec(typ reflect.Type, f *reflect.StructField, fixedSize *int) {
    83  	p.enc = nil
    84  	p.dec = nil
    85  	p.siz = nil
    86  	p.t = typ
    87  
    88  	switch typ.Kind() {
    89  	case reflect.Bool: // bool
    90  		p.enc = (*Buffer).enc_bool
    91  		p.dec = (*Buffer).dec_bool
    92  		*fixedSize += 1
    93  	case reflect.Int8, reflect.Uint8: // int8 uint8
    94  		p.enc = (*Buffer).enc_uint8
    95  		p.dec = (*Buffer).dec_uint8
    96  		*fixedSize += 1
    97  	case reflect.Int16, reflect.Uint16: // int16 uint16
    98  		p.enc = (*Buffer).enc_uint16
    99  		p.dec = (*Buffer).dec_uint16
   100  		*fixedSize += 2
   101  	case reflect.Int32, reflect.Uint32, reflect.Float32: // int32 uint32 float32
   102  		p.enc = (*Buffer).enc_uint32
   103  		p.dec = (*Buffer).dec_uint32
   104  		*fixedSize += 4
   105  	case reflect.Int64, reflect.Uint64, reflect.Float64: // int64 uint64 float64
   106  		p.enc = (*Buffer).enc_uint64
   107  		p.dec = (*Buffer).dec_uint64
   108  		*fixedSize += 8
   109  	case reflect.String: // string
   110  		p.enc = (*Buffer).enc_string
   111  		p.dec = (*Buffer).dec_string
   112  		p.siz = (*Buffer).size_string
   113  		*fixedSize += 2
   114  	case reflect.Ptr: // cstruct ptr
   115  		if t2 := typ.Elem(); t2.Kind() == reflect.Struct {
   116  			p.stype = t2
   117  			p.sprop = getPropertiesLocked(p.stype)
   118  			p.enc = (*Buffer).enc_substruct_ptr
   119  			p.dec = (*Buffer).dec_substruct_ptr
   120  			p.siz = (*Buffer).size_substruct_ptr
   121  		} else {
   122  			panic("cstruct: unknow type. field name =" + f.Name)
   123  		}
   124  	case reflect.Struct: // cstruct
   125  		p.stype = typ
   126  		p.sprop = getPropertiesLocked(p.stype)
   127  		p.enc = (*Buffer).enc_substruct
   128  		p.dec = (*Buffer).dec_substruct
   129  		p.siz = (*Buffer).size_substruct
   130  	case reflect.Slice:
   131  		*fixedSize += 2
   132  		switch t2 := typ.Elem(); t2.Kind() {
   133  		case reflect.Uint8, reflect.Int8: // []byte []uint8 []int8
   134  			p.enc = (*Buffer).enc_slice_byte
   135  			p.dec = (*Buffer).dec_slice_byte
   136  			p.siz = (*Buffer).size_slice_byte
   137  		case reflect.Bool: // []bool
   138  			p.enc = (*Buffer).enc_slice_bool
   139  			p.dec = (*Buffer).dec_slice_bool
   140  			p.siz = (*Buffer).size_slice_bool
   141  		case reflect.Uint16, reflect.Int16: // []uint16 []int16
   142  			p.enc = (*Buffer).enc_slice_uint16
   143  			p.dec = (*Buffer).dec_slice_uint16
   144  			p.siz = (*Buffer).size_slice_uint16
   145  		case reflect.Uint32, reflect.Int32, reflect.Float32: // []uint32 []int32 []float32
   146  			p.enc = (*Buffer).enc_slice_uint32
   147  			p.dec = (*Buffer).dec_slice_uint32
   148  			p.siz = (*Buffer).size_slice_uint32
   149  		case reflect.Uint64, reflect.Int64, reflect.Float64: // []uint64 []int64 []float64
   150  			p.enc = (*Buffer).enc_slice_uint64
   151  			p.dec = (*Buffer).dec_slice_uint64
   152  			p.siz = (*Buffer).size_slice_uint64
   153  		case reflect.String: // []string
   154  			p.enc = (*Buffer).enc_slice_string
   155  			p.dec = (*Buffer).dec_slice_string
   156  			p.siz = (*Buffer).size_slice_string
   157  		case reflect.Struct: // [] cstruct
   158  			p.stype = t2
   159  			p.sprop = getPropertiesLocked(p.stype)
   160  			p.enc = (*Buffer).enc_slice_substruct
   161  			p.dec = (*Buffer).dec_slice_substruct
   162  			p.siz = (*Buffer).size_slice_substruct
   163  		case reflect.Ptr: // []*cstruct
   164  			switch t3 := t2.Elem(); t3.Kind() {
   165  			case reflect.Struct:
   166  				p.stype = t3
   167  				p.sprop = getPropertiesLocked(p.stype)
   168  				if OptionSliceIgnoreNil == false {
   169  					p.enc = (*Buffer).enc_slice_substruct_ptr
   170  					p.dec = (*Buffer).dec_slice_substruct_ptr
   171  					p.siz = (*Buffer).size_slice_substruct_ptr
   172  				} else {
   173  					p.enc = (*Buffer).enc_slice_substruct_ptr_ignore_nil
   174  					p.dec = (*Buffer).dec_slice_substruct_ptr_ignore_nil
   175  					p.siz = (*Buffer).size_slice_substruct_ptr_ignore_nil
   176  				}
   177  			default:
   178  				panic("cstruct: unknow type. field name = " + f.Name)
   179  			}
   180  		case reflect.Slice:
   181  			switch t2.Elem().Kind() {
   182  			case reflect.Uint8:
   183  				p.enc = (*Buffer).enc_slice_slice_byte
   184  				p.dec = (*Buffer).dec_slice_slice_byte
   185  				p.siz = (*Buffer).size_slice_slice_byte
   186  			default:
   187  				panic("cstruct: unknow type. field name = " + f.Name)
   188  			}
   189  		default:
   190  			panic("cstruct: unknow type. field name = " + f.Name)
   191  		}
   192  	case reflect.Array:
   193  		switch t2 := typ.Elem(); t2.Kind() {
   194  		case reflect.Uint8, reflect.Int8, reflect.Bool: // [n]byte [n]uint8 [n]int8 [n]bool
   195  			p.enc = (*Buffer).enc_array_byte
   196  			p.dec = (*Buffer).dec_array_byte
   197  			p.siz = (*Buffer).size_array_byte
   198  		case reflect.Uint16, reflect.Int16: // [n]uint16 [n]int16
   199  			p.enc = (*Buffer).enc_array_uint16
   200  			p.dec = (*Buffer).dec_array_uint16
   201  			p.siz = (*Buffer).size_array_uint16
   202  		case reflect.Uint32, reflect.Int32, reflect.Float32: // [n]uint32 [n]int32 [n]float32
   203  			p.enc = (*Buffer).enc_array_uint32
   204  			p.dec = (*Buffer).dec_array_uint32
   205  			p.siz = (*Buffer).size_array_uint32
   206  		case reflect.Uint64, reflect.Int64, reflect.Float64: // [n]uint64 [n]int64 [n]float64
   207  			p.enc = (*Buffer).enc_array_uint64
   208  			p.dec = (*Buffer).dec_array_uint64
   209  			p.siz = (*Buffer).size_array_uint64
   210  		case reflect.Struct: // [n]cstruct
   211  			p.stype = t2
   212  			p.sprop = getPropertiesLocked(p.stype)
   213  			p.enc = (*Buffer).enc_array_substruct
   214  			p.dec = (*Buffer).dec_array_substruct
   215  			p.siz = (*Buffer).size_array_substruct
   216  		default:
   217  			panic("cstruct: unknow type. field name = " + f.Name)
   218  		}
   219  	default:
   220  		panic("cstruct: unknow type. field name = " + f.Name)
   221  	}
   222  }