load.go (7508B)
1 package mangler 2 3 import ( 4 "reflect" 5 ) 6 7 // loadMangler is the top-most Mangler load function. It guarantees that a Mangler 8 // function will be returned for given value interface{} and reflected type. Else panics. 9 func loadMangler(a any, t reflect.Type) Mangler { 10 // Load mangler function 11 mng, rmng := load(a, t) 12 13 if mng != nil { 14 // Use preferred mangler. 15 return mng 16 } 17 18 if rmng != nil { 19 // Wrap reflect mangler to handle iface 20 return func(buf []byte, a any) []byte { 21 return rmng(buf, reflect.ValueOf(a)) 22 } 23 } 24 25 // No mangler function could be determined 26 panic("cannot mangle type: " + t.String()) 27 } 28 29 // load will load a Mangler or reflect Mangler for given type and iface 'a'. 30 // Note: allocates new interface value if nil provided, i.e. if coming via reflection. 31 func load(a any, t reflect.Type) (Mangler, rMangler) { 32 if t == nil { 33 // There is no reflect type to search by 34 panic("cannot mangle nil interface{} type") 35 } 36 37 if a == nil { 38 // Alloc new iface instance 39 v := reflect.New(t).Elem() 40 a = v.Interface() 41 } 42 43 // Check for Mangled implementation. 44 if _, ok := a.(Mangled); ok { 45 return mangle_mangled, nil 46 } 47 48 // Search mangler by reflection. 49 mng, rmng := loadReflect(t) 50 if mng != nil { 51 return mng, nil 52 } 53 54 // Prefer iface mangler, else, reflected. 55 return loadIface(a), rmng 56 } 57 58 // loadIface is used as a near-last-resort interface{} type switch 59 // loader for types implementating other known (slower) functions. 60 func loadIface(a any) Mangler { 61 switch a.(type) { 62 case binarymarshaler: 63 return mangle_binary 64 case stringer: 65 return mangle_stringer 66 case textmarshaler: 67 return mangle_text 68 case jsonmarshaler: 69 return mangle_json 70 default: 71 return nil 72 } 73 } 74 75 // loadReflect will load a Mangler (or rMangler) function for the given reflected type info. 76 // NOTE: this is used as the top level load function for nested reflective searches. 77 func loadReflect(t reflect.Type) (Mangler, rMangler) { 78 switch t.Kind() { 79 case reflect.Pointer: 80 return loadReflectPtr(t.Elem()) 81 82 case reflect.String: 83 return mangle_string, nil 84 85 case reflect.Array: 86 return nil, loadReflectArray(t.Elem()) 87 88 case reflect.Slice: 89 // Element type 90 et := t.Elem() 91 92 // Preferably look for known slice mangler func 93 if mng := loadReflectKnownSlice(et); mng != nil { 94 return mng, nil 95 } 96 97 // Else handle as array elements 98 return nil, loadReflectArray(et) 99 100 case reflect.Map: 101 return nil, loadReflectMap(t.Key(), t.Elem()) 102 103 case reflect.Bool: 104 return mangle_bool, nil 105 106 case reflect.Int, 107 reflect.Uint, 108 reflect.Uintptr: 109 return mangle_platform_int, nil 110 111 case reflect.Int8, reflect.Uint8: 112 return mangle_8bit, nil 113 114 case reflect.Int16, reflect.Uint16: 115 return mangle_16bit, nil 116 117 case reflect.Int32, reflect.Uint32: 118 return mangle_32bit, nil 119 120 case reflect.Int64, reflect.Uint64: 121 return mangle_64bit, nil 122 123 case reflect.Float32: 124 return mangle_32bit, nil 125 126 case reflect.Float64: 127 return mangle_64bit, nil 128 129 case reflect.Complex64: 130 return mangle_64bit, nil 131 132 case reflect.Complex128: 133 return mangle_128bit, nil 134 135 default: 136 return nil, nil 137 } 138 } 139 140 // loadReflectPtr loads a Mangler (or rMangler) function for a ptr's element type. 141 // This also handles further dereferencing of any further ptr indrections (e.g. ***int). 142 func loadReflectPtr(et reflect.Type) (Mangler, rMangler) { 143 count := 1 144 145 // Iteratively dereference ptrs 146 for et.Kind() == reflect.Pointer { 147 et = et.Elem() 148 count++ 149 } 150 151 if et.Kind() == reflect.Array { 152 // Array elem type 153 at := et.Elem() 154 155 // Special case of addressable (sliceable) array 156 if mng := loadReflectKnownSlice(at); mng != nil { 157 rmng := array_to_slice_mangler(mng) 158 return nil, deref_ptr_rmangler(rmng, count) 159 } 160 161 // Look for an array mangler function, this will 162 // access elements by index using reflect.Value and 163 // pass each one to a separate mangler function. 164 if rmng := loadReflectArray(at); rmng != nil { 165 return nil, deref_ptr_rmangler(rmng, count) 166 } 167 168 return nil, nil 169 } 170 171 // Try remove a layer of derefs by loading a mangler 172 // for a known ptr kind. The less reflection the better! 173 if mng := loadReflectKnownPtr(et); mng != nil { 174 if count == 1 { 175 return mng, nil 176 } 177 return nil, deref_ptr_mangler(mng, count-1) 178 } 179 180 // Search for ptr elemn type mangler 181 if mng, rmng := load(nil, et); mng != nil { 182 return nil, deref_ptr_mangler(mng, count) 183 } else if rmng != nil { 184 return nil, deref_ptr_rmangler(rmng, count) 185 } 186 187 return nil, nil 188 } 189 190 // loadReflectKnownPtr loads a Mangler function for a known ptr-of-element type (in this case, primtive ptrs). 191 func loadReflectKnownPtr(et reflect.Type) Mangler { 192 switch et.Kind() { 193 case reflect.String: 194 return mangle_string_ptr 195 196 case reflect.Bool: 197 return mangle_bool_ptr 198 199 case reflect.Int, 200 reflect.Uint, 201 reflect.Uintptr: 202 return mangle_platform_int_ptr 203 204 case reflect.Int8, reflect.Uint8: 205 return mangle_8bit_ptr 206 207 case reflect.Int16, reflect.Uint16: 208 return mangle_16bit_ptr 209 210 case reflect.Int32, reflect.Uint32: 211 return mangle_32bit_ptr 212 213 case reflect.Int64, reflect.Uint64: 214 return mangle_64bit_ptr 215 216 case reflect.Float32: 217 return mangle_32bit_ptr 218 219 case reflect.Float64: 220 return mangle_64bit_ptr 221 222 case reflect.Complex64: 223 return mangle_64bit_ptr 224 225 case reflect.Complex128: 226 return mangle_128bit_ptr 227 228 default: 229 return nil 230 } 231 } 232 233 // loadReflectKnownSlice loads a Mangler function for a known slice-of-element type (in this case, primtives). 234 func loadReflectKnownSlice(et reflect.Type) Mangler { 235 switch et.Kind() { 236 case reflect.String: 237 return mangle_string_slice 238 239 case reflect.Bool: 240 return mangle_bool_slice 241 242 case reflect.Int, 243 reflect.Uint, 244 reflect.Uintptr: 245 return mangle_platform_int_slice 246 247 case reflect.Int8, reflect.Uint8: 248 return mangle_8bit_slice 249 250 case reflect.Int16, reflect.Uint16: 251 return mangle_16bit_slice 252 253 case reflect.Int32, reflect.Uint32: 254 return mangle_32bit_slice 255 256 case reflect.Int64, reflect.Uint64: 257 return mangle_64bit_slice 258 259 case reflect.Float32: 260 return mangle_32bit_slice 261 262 case reflect.Float64: 263 return mangle_64bit_slice 264 265 case reflect.Complex64: 266 return mangle_64bit_slice 267 268 case reflect.Complex128: 269 return mangle_128bit_slice 270 271 default: 272 return nil 273 } 274 } 275 276 // loadReflectArray loads an rMangler function for an array (or slice) or given element type. 277 func loadReflectArray(et reflect.Type) rMangler { 278 // Search via reflected array element type 279 if mng, rmng := load(nil, et); mng != nil { 280 return iter_array_mangler(mng) 281 } else if rmng != nil { 282 return iter_array_rmangler(rmng) 283 } 284 return nil 285 } 286 287 // loadReflectMap loads an rMangler function for a map of given key and value types. 288 func loadReflectMap(kt, vt reflect.Type) rMangler { 289 var kmng, vmng rMangler 290 291 // Search for mangler for key type 292 mng, rmng := load(nil, kt) 293 294 switch { 295 // Wrap key mangler to reflect 296 case mng != nil: 297 mng := mng // take our own ptr 298 kmng = func(buf []byte, v reflect.Value) []byte { 299 return mng(buf, v.Interface()) 300 } 301 302 // Use reflect key mangler as-is 303 case rmng != nil: 304 kmng = rmng 305 306 // No mangler found 307 default: 308 return nil 309 } 310 311 // Search for mangler for value type 312 mng, rmng = load(nil, vt) 313 314 switch { 315 // Wrap value mangler to reflect 316 case mng != nil: 317 mng := mng // take our own ptr 318 vmng = func(buf []byte, v reflect.Value) []byte { 319 return mng(buf, v.Interface()) 320 } 321 322 // Use reflect value mangler as-is 323 case rmng != nil: 324 vmng = rmng 325 326 // No mangler found 327 default: 328 return nil 329 } 330 331 // Wrap key/value manglers in map iter 332 return iter_map_rmangler(kmng, vmng) 333 }