github.com/clubpay/ronykit/kit@v0.14.4-0.20240515065620-d0dace45cbc7/utils/reflector/obj.go (about)

     1  package reflector
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"unsafe"
     7  
     8  	"github.com/clubpay/ronykit/kit"
     9  )
    10  
    11  var (
    12  	registered          = map[reflect.Type]*Reflected{}
    13  	errInvalidFieldType = func(s string) error { return fmt.Errorf("the field type does not match: %s", s) }
    14  )
    15  
    16  // emptyInterface is the header for an any value.
    17  type emptyInterface struct {
    18  	_    uint64
    19  	word unsafe.Pointer
    20  }
    21  
    22  type FieldInfo struct {
    23  	idx    int
    24  	f      reflect.StructField
    25  	name   string
    26  	offset uintptr
    27  	typ    reflect.Type
    28  	unsafe bool
    29  }
    30  
    31  func (f FieldInfo) Kind() reflect.Kind {
    32  	if f.typ == nil {
    33  		return reflect.Invalid
    34  	}
    35  
    36  	return f.typ.Kind()
    37  }
    38  
    39  func (f FieldInfo) Type() reflect.StructField {
    40  	return f.f
    41  }
    42  
    43  type Fields map[string]FieldInfo
    44  
    45  func (fields Fields) Get(m kit.Message, fieldName string) any {
    46  	fi := fields[fieldName]
    47  	mVal := reflect.Indirect(reflect.ValueOf(m)).Field(fi.idx)
    48  	switch fi.Kind() {
    49  	default:
    50  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
    51  		return mVal.Int()
    52  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
    53  		return mVal.Uint()
    54  	case reflect.String:
    55  		return mVal.String()
    56  	case reflect.Float64, reflect.Float32:
    57  		return mVal.Float()
    58  	case reflect.Bool:
    59  		return mVal.Bool()
    60  	}
    61  
    62  	if !mVal.CanInterface() {
    63  		return nil
    64  	}
    65  
    66  	return mVal
    67  }
    68  
    69  func (fields Fields) GetInt(m kit.Message, fieldName string) (int, error) {
    70  	fi := fields[fieldName]
    71  	if k := fi.Kind(); k != reflect.Int {
    72  		return 0, errInvalidFieldType(k.String())
    73  	}
    74  
    75  	ptr := unsafe.Add((*emptyInterface)(unsafe.Pointer(&m)).word, fi.offset)
    76  
    77  	return *(*int)(ptr), nil
    78  }
    79  
    80  func (fields Fields) GetIntDefault(m kit.Message, fieldName string, def int) int {
    81  	v, err := fields.GetInt(m, fieldName)
    82  	if err != nil {
    83  		return def
    84  	}
    85  
    86  	return v
    87  }
    88  
    89  func (fields Fields) GetUInt(m kit.Message, fieldName string) (uint, error) {
    90  	fi := fields[fieldName]
    91  	if k := fi.Kind(); k != reflect.Uint {
    92  		return 0, errInvalidFieldType(k.String())
    93  	}
    94  
    95  	ptr := unsafe.Add((*emptyInterface)(unsafe.Pointer(&m)).word, fi.offset)
    96  
    97  	return *(*uint)(ptr), nil
    98  }
    99  
   100  func (fields Fields) GetUIntDefault(m kit.Message, fieldName string, def uint) uint {
   101  	v, err := fields.GetUInt(m, fieldName)
   102  	if err != nil {
   103  		return def
   104  	}
   105  
   106  	return v
   107  }
   108  
   109  func (fields Fields) GetInt64(m kit.Message, fieldName string) (int64, error) {
   110  	fi := fields[fieldName]
   111  	if k := fi.Kind(); k != reflect.Int64 {
   112  		return 0, errInvalidFieldType(k.String())
   113  	}
   114  
   115  	ptr := unsafe.Add((*emptyInterface)(unsafe.Pointer(&m)).word, fi.offset)
   116  
   117  	return *(*int64)(ptr), nil
   118  }
   119  
   120  func (fields Fields) GetInt64Default(m kit.Message, fieldName string, def int64) int64 {
   121  	v, err := fields.GetInt64(m, fieldName)
   122  	if err != nil {
   123  		return def
   124  	}
   125  
   126  	return v
   127  }
   128  
   129  func (fields Fields) GetUInt64(m kit.Message, fieldName string) (uint64, error) {
   130  	fi := fields[fieldName]
   131  	if k := fi.Kind(); k != reflect.Uint64 {
   132  		return 0, errInvalidFieldType(k.String())
   133  	}
   134  
   135  	ptr := unsafe.Add((*emptyInterface)(unsafe.Pointer(&m)).word, fi.offset)
   136  
   137  	return *(*uint64)(ptr), nil
   138  }
   139  
   140  func (fields Fields) GetUInt64Default(m kit.Message, fieldName string, def uint64) uint64 {
   141  	v, err := fields.GetUInt64(m, fieldName)
   142  	if err != nil {
   143  		return def
   144  	}
   145  
   146  	return v
   147  }
   148  
   149  func (fields Fields) GetInt32(m kit.Message, fieldName string) (int32, error) {
   150  	fi := fields[fieldName]
   151  	if k := fi.Kind(); k != reflect.Int32 {
   152  		return 0, errInvalidFieldType(k.String())
   153  	}
   154  
   155  	ptr := unsafe.Add((*emptyInterface)(unsafe.Pointer(&m)).word, fi.offset)
   156  
   157  	return *(*int32)(ptr), nil
   158  }
   159  
   160  func (fields Fields) GetInt32Default(m kit.Message, fieldName string, def int32) int32 {
   161  	v, err := fields.GetInt32(m, fieldName)
   162  	if err != nil {
   163  		return def
   164  	}
   165  
   166  	return v
   167  }
   168  
   169  func (fields Fields) GetUInt32(m kit.Message, fieldName string) (uint32, error) {
   170  	fi := fields[fieldName]
   171  	if k := fi.Kind(); k != reflect.Uint32 {
   172  		return 0, errInvalidFieldType(k.String())
   173  	}
   174  
   175  	ptr := unsafe.Add((*emptyInterface)(unsafe.Pointer(&m)).word, fi.offset)
   176  
   177  	return *(*uint32)(ptr), nil
   178  }
   179  
   180  func (fields Fields) GetUInt32Default(m kit.Message, fieldName string, def uint32) uint32 {
   181  	v, err := fields.GetUInt32(m, fieldName)
   182  	if err != nil {
   183  		return def
   184  	}
   185  
   186  	return v
   187  }
   188  
   189  func (fields Fields) GetString(m kit.Message, fieldName string) (string, error) {
   190  	fi := fields[fieldName]
   191  	if k := fi.Kind(); k != reflect.String {
   192  		return "", errInvalidFieldType(k.String())
   193  	}
   194  
   195  	ptr := unsafe.Add((*emptyInterface)(unsafe.Pointer(&m)).word, fi.offset)
   196  
   197  	return *(*string)(ptr), nil
   198  }
   199  
   200  func (fields Fields) GetStringDefault(m kit.Message, fieldName string, def string) string {
   201  	v, err := fields.GetString(m, fieldName)
   202  	if err != nil {
   203  		return def
   204  	}
   205  
   206  	return v
   207  }
   208  
   209  func (fields Fields) WalkFields(cb func(key string, f FieldInfo)) {
   210  	for k, f := range fields {
   211  		cb(k, f)
   212  	}
   213  }
   214  
   215  type Reflected struct {
   216  	obj   Fields
   217  	byTag map[string]Fields
   218  	typ   reflect.Type
   219  }
   220  
   221  func (r Reflected) ByTag(t string) (Fields, bool) {
   222  	f, ok := r.byTag[t]
   223  
   224  	return f, ok
   225  }
   226  
   227  func (r Reflected) Obj() Fields {
   228  	return r.obj
   229  }
   230  
   231  func (r Reflected) Type() reflect.Type {
   232  	return r.typ
   233  }