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 }