codeberg.org/gruf/go-mangler@v1.3.0/load.go (about) 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 fn 11 mng := load(a, t) 12 if mng != nil { 13 return mng 14 } 15 16 // No mangler function could be determined 17 panic("cannot mangle type: " + t.String()) 18 } 19 20 // load will load a Mangler or reflect Mangler for given type and iface 'a'. 21 // Note: allocates new interface value if nil provided, i.e. if coming via reflection. 22 func load(a any, t reflect.Type) Mangler { 23 if t == nil { 24 // There is no reflect type to search by 25 panic("cannot mangle nil interface{} type") 26 } 27 28 if a == nil { 29 // Alloc new iface instance 30 v := reflect.New(t).Elem() 31 a = v.Interface() 32 } 33 34 // Check for Mangled implementation. 35 if _, ok := a.(Mangled); ok { 36 return mangle_mangled 37 } 38 39 // Search mangler by reflection. 40 mng := loadReflect(t) 41 if mng != nil { 42 return mng 43 } 44 45 // Prefer iface mangler. 46 mng = loadIface(a) 47 if mng != nil { 48 return mng 49 } 50 51 return nil 52 } 53 54 // loadIface is used as a near-last-resort interface{} type switch 55 // loader for types implementating other known (slower) functions. 56 func loadIface(a any) Mangler { 57 switch a.(type) { 58 case binarymarshaler: 59 return mangle_binary 60 case byteser: 61 return mangle_byteser 62 case stringer: 63 return mangle_stringer 64 case textmarshaler: 65 return mangle_text 66 case jsonmarshaler: 67 return mangle_json 68 default: 69 return nil 70 } 71 } 72 73 // loadReflect will load a Mangler (or rMangler) function for the given reflected type info. 74 // NOTE: this is used as the top level load function for nested reflective searches. 75 func loadReflect(t reflect.Type) Mangler { 76 switch t.Kind() { 77 case reflect.Pointer: 78 return loadReflectPtr(t) 79 80 case reflect.String: 81 return mangle_string 82 83 case reflect.Struct: 84 return loadReflectStruct(t) 85 86 case reflect.Array: 87 return loadReflectArray(t) 88 89 case reflect.Slice: 90 return loadReflectSlice(t) 91 92 case reflect.Map: 93 return loadReflectMap(t) 94 95 case reflect.Bool: 96 return mangle_bool 97 98 case reflect.Int, 99 reflect.Uint, 100 reflect.Uintptr: 101 return mangle_platform_int() 102 103 case reflect.Int8, reflect.Uint8: 104 return mangle_8bit 105 106 case reflect.Int16, reflect.Uint16: 107 return mangle_16bit 108 109 case reflect.Int32, reflect.Uint32: 110 return mangle_32bit 111 112 case reflect.Int64, reflect.Uint64: 113 return mangle_64bit 114 115 case reflect.Float32: 116 return mangle_32bit 117 118 case reflect.Float64: 119 return mangle_64bit 120 121 case reflect.Complex64: 122 return mangle_64bit 123 124 case reflect.Complex128: 125 return mangle_128bit 126 127 default: 128 return nil 129 } 130 } 131 132 // loadReflectPtr loads a Mangler (or rMangler) function for a ptr's element type. 133 // This also handles further dereferencing of any further ptr indrections (e.g. ***int). 134 func loadReflectPtr(t reflect.Type) Mangler { 135 var count int 136 137 // Elem 138 et := t 139 140 // Iteratively dereference ptrs 141 for et.Kind() == reflect.Pointer { 142 et = et.Elem() 143 count++ 144 } 145 146 // Search for ptr elemn type mangler. 147 if mng := load(nil, et); mng != nil { 148 return deref_ptr_mangler(et, mng, count) 149 } 150 151 return nil 152 } 153 154 // loadReflectKnownSlice loads a Mangler function for a 155 // known slice-of-element type (in this case, primtives). 156 func loadReflectKnownSlice(et reflect.Type) Mangler { 157 switch et.Kind() { 158 case reflect.String: 159 return mangle_string_slice 160 161 case reflect.Bool: 162 return mangle_bool_slice 163 164 case reflect.Int, 165 reflect.Uint, 166 reflect.Uintptr: 167 return mangle_platform_int_slice() 168 169 case reflect.Int8, reflect.Uint8: 170 return mangle_8bit_slice 171 172 case reflect.Int16, reflect.Uint16: 173 return mangle_16bit_slice 174 175 case reflect.Int32, reflect.Uint32: 176 return mangle_32bit_slice 177 178 case reflect.Int64, reflect.Uint64: 179 return mangle_64bit_slice 180 181 case reflect.Float32: 182 return mangle_32bit_slice 183 184 case reflect.Float64: 185 return mangle_64bit_slice 186 187 case reflect.Complex64: 188 return mangle_64bit_slice 189 190 case reflect.Complex128: 191 return mangle_128bit_slice 192 193 default: 194 return nil 195 } 196 } 197 198 // loadReflectSlice ... 199 func loadReflectSlice(t reflect.Type) Mangler { 200 // Element type 201 et := t.Elem() 202 203 // Preferably look for known slice mangler func 204 if mng := loadReflectKnownSlice(et); mng != nil { 205 return mng 206 } 207 208 // Fallback to nested mangler iteration. 209 if mng := load(nil, et); mng != nil { 210 return iter_slice_mangler(t, mng) 211 } 212 213 return nil 214 } 215 216 // loadReflectArray ... 217 func loadReflectArray(t reflect.Type) Mangler { 218 // Element type. 219 et := t.Elem() 220 221 // Use manglers for nested iteration. 222 if mng := load(nil, et); mng != nil { 223 return iter_array_mangler(t, mng) 224 } 225 226 return nil 227 } 228 229 // loadReflectMap ... 230 func loadReflectMap(t reflect.Type) Mangler { 231 // Map types. 232 kt := t.Key() 233 et := t.Elem() 234 235 // Load manglers. 236 kmng := load(nil, kt) 237 emng := load(nil, et) 238 239 // Use manglers for nested iteration. 240 if kmng != nil && emng != nil { 241 return iter_map_mangler(t, kmng, emng) 242 } 243 244 return nil 245 } 246 247 // loadReflectStruct ... 248 func loadReflectStruct(t reflect.Type) Mangler { 249 var mngs []Mangler 250 251 // Gather manglers for all fields. 252 for i := 0; i < t.NumField(); i++ { 253 field := t.Field(i) 254 255 // Load mangler for field type. 256 mng := load(nil, field.Type) 257 if mng == nil { 258 return nil 259 } 260 261 // Append next to map. 262 mngs = append(mngs, mng) 263 } 264 265 // Use manglers for nested iteration. 266 return iter_struct_mangler(t, mngs) 267 }