gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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 }