| 
									
										
										
										
											2022-11-11 12:18:38 +01:00
										 |  |  | package mangler | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"reflect" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // loadMangler is the top-most Mangler load function. It guarantees that a Mangler | 
					
						
							|  |  |  | // function will be returned for given value interface{} and reflected type. Else panics. | 
					
						
							|  |  |  | func loadMangler(a any, t reflect.Type) Mangler { | 
					
						
							|  |  |  | 	// Load mangler function | 
					
						
							|  |  |  | 	mng, rmng := load(a, t) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-19 09:36:38 +00:00
										 |  |  | 	if mng != nil { | 
					
						
							|  |  |  | 		// Use preferred mangler. | 
					
						
							|  |  |  | 		return mng | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-11 12:18:38 +01:00
										 |  |  | 	if rmng != nil { | 
					
						
							|  |  |  | 		// Wrap reflect mangler to handle iface | 
					
						
							|  |  |  | 		return func(buf []byte, a any) []byte { | 
					
						
							|  |  |  | 			return rmng(buf, reflect.ValueOf(a)) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-19 09:36:38 +00:00
										 |  |  | 	// No mangler function could be determined | 
					
						
							|  |  |  | 	panic("cannot mangle type: " + t.String()) | 
					
						
							| 
									
										
										
										
											2022-11-11 12:18:38 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // load will load a Mangler or reflect Mangler for given type and iface 'a'. | 
					
						
							|  |  |  | // Note: allocates new interface value if nil provided, i.e. if coming via reflection. | 
					
						
							|  |  |  | func load(a any, t reflect.Type) (Mangler, rMangler) { | 
					
						
							|  |  |  | 	if t == nil { | 
					
						
							|  |  |  | 		// There is no reflect type to search by | 
					
						
							|  |  |  | 		panic("cannot mangle nil interface{} type") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if a == nil { | 
					
						
							|  |  |  | 		// Alloc new iface instance | 
					
						
							|  |  |  | 		v := reflect.New(t).Elem() | 
					
						
							|  |  |  | 		a = v.Interface() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-19 09:36:38 +00:00
										 |  |  | 	// Check for Mangled implementation. | 
					
						
							|  |  |  | 	if _, ok := a.(Mangled); ok { | 
					
						
							|  |  |  | 		return mangle_mangled, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Search mangler by reflection. | 
					
						
							|  |  |  | 	mng, rmng := loadReflect(t) | 
					
						
							|  |  |  | 	if mng != nil { | 
					
						
							| 
									
										
										
										
											2022-11-11 12:18:38 +01:00
										 |  |  | 		return mng, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-19 09:36:38 +00:00
										 |  |  | 	// Prefer iface mangler, else, reflected. | 
					
						
							|  |  |  | 	return loadIface(a), rmng | 
					
						
							| 
									
										
										
										
											2022-11-11 12:18:38 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-19 09:36:38 +00:00
										 |  |  | // loadIface is used as a near-last-resort interface{} type switch | 
					
						
							|  |  |  | // loader for types implementating other known (slower) functions. | 
					
						
							| 
									
										
										
										
											2022-11-11 12:18:38 +01:00
										 |  |  | func loadIface(a any) Mangler { | 
					
						
							|  |  |  | 	switch a.(type) { | 
					
						
							| 
									
										
										
										
											2023-02-19 09:36:38 +00:00
										 |  |  | 	case binarymarshaler: | 
					
						
							| 
									
										
										
										
											2022-11-11 12:18:38 +01:00
										 |  |  | 		return mangle_binary | 
					
						
							| 
									
										
										
										
											2023-02-19 09:36:38 +00:00
										 |  |  | 	case stringer: | 
					
						
							|  |  |  | 		return mangle_stringer | 
					
						
							|  |  |  | 	case textmarshaler: | 
					
						
							|  |  |  | 		return mangle_text | 
					
						
							|  |  |  | 	case jsonmarshaler: | 
					
						
							|  |  |  | 		return mangle_json | 
					
						
							| 
									
										
										
										
											2022-11-11 12:18:38 +01:00
										 |  |  | 	default: | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // loadReflect will load a Mangler (or rMangler) function for the given reflected type info. | 
					
						
							|  |  |  | // NOTE: this is used as the top level load function for nested reflective searches. | 
					
						
							|  |  |  | func loadReflect(t reflect.Type) (Mangler, rMangler) { | 
					
						
							|  |  |  | 	switch t.Kind() { | 
					
						
							|  |  |  | 	case reflect.Pointer: | 
					
						
							|  |  |  | 		return loadReflectPtr(t.Elem()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.String: | 
					
						
							|  |  |  | 		return mangle_string, nil | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.Array: | 
					
						
							|  |  |  | 		return nil, loadReflectArray(t.Elem()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.Slice: | 
					
						
							|  |  |  | 		// Element type | 
					
						
							|  |  |  | 		et := t.Elem() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Preferably look for known slice mangler func | 
					
						
							|  |  |  | 		if mng := loadReflectKnownSlice(et); mng != nil { | 
					
						
							|  |  |  | 			return mng, nil | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Else handle as array elements | 
					
						
							|  |  |  | 		return nil, loadReflectArray(et) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.Map: | 
					
						
							|  |  |  | 		return nil, loadReflectMap(t.Key(), t.Elem()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.Bool: | 
					
						
							|  |  |  | 		return mangle_bool, nil | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.Int, | 
					
						
							|  |  |  | 		reflect.Uint, | 
					
						
							|  |  |  | 		reflect.Uintptr: | 
					
						
							|  |  |  | 		return mangle_platform_int, nil | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-06 10:16:09 +00:00
										 |  |  | 	case reflect.Int8, reflect.Uint8: | 
					
						
							| 
									
										
										
										
											2022-11-11 12:18:38 +01:00
										 |  |  | 		return mangle_8bit, nil | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-06 10:16:09 +00:00
										 |  |  | 	case reflect.Int16, reflect.Uint16: | 
					
						
							| 
									
										
										
										
											2022-11-11 12:18:38 +01:00
										 |  |  | 		return mangle_16bit, nil | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-06 10:16:09 +00:00
										 |  |  | 	case reflect.Int32, reflect.Uint32: | 
					
						
							| 
									
										
										
										
											2022-11-11 12:18:38 +01:00
										 |  |  | 		return mangle_32bit, nil | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-06 10:16:09 +00:00
										 |  |  | 	case reflect.Int64, reflect.Uint64: | 
					
						
							| 
									
										
										
										
											2022-11-11 12:18:38 +01:00
										 |  |  | 		return mangle_64bit, nil | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.Float32: | 
					
						
							|  |  |  | 		return mangle_32bit, nil | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.Float64: | 
					
						
							|  |  |  | 		return mangle_64bit, nil | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.Complex64: | 
					
						
							|  |  |  | 		return mangle_64bit, nil | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.Complex128: | 
					
						
							|  |  |  | 		return mangle_128bit, nil | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		return nil, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // loadReflectPtr loads a Mangler (or rMangler) function for a ptr's element type. | 
					
						
							|  |  |  | // This also handles further dereferencing of any further ptr indrections (e.g. ***int). | 
					
						
							|  |  |  | func loadReflectPtr(et reflect.Type) (Mangler, rMangler) { | 
					
						
							|  |  |  | 	count := 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Iteratively dereference ptrs | 
					
						
							|  |  |  | 	for et.Kind() == reflect.Pointer { | 
					
						
							|  |  |  | 		et = et.Elem() | 
					
						
							|  |  |  | 		count++ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if et.Kind() == reflect.Array { | 
					
						
							| 
									
										
										
										
											2023-02-19 09:36:38 +00:00
										 |  |  | 		// Array elem type | 
					
						
							|  |  |  | 		at := et.Elem() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-11 12:18:38 +01:00
										 |  |  | 		// Special case of addressable (sliceable) array | 
					
						
							| 
									
										
										
										
											2023-02-19 09:36:38 +00:00
										 |  |  | 		if mng := loadReflectKnownSlice(at); mng != nil { | 
					
						
							|  |  |  | 			rmng := array_to_slice_mangler(mng) | 
					
						
							|  |  |  | 			return nil, deref_ptr_rmangler(rmng, count) | 
					
						
							| 
									
										
										
										
											2022-11-11 12:18:38 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Look for an array mangler function, this will | 
					
						
							|  |  |  | 		// access elements by index using reflect.Value and | 
					
						
							|  |  |  | 		// pass each one to a separate mangler function. | 
					
						
							| 
									
										
										
										
											2023-02-19 09:36:38 +00:00
										 |  |  | 		if rmng := loadReflectArray(at); rmng != nil { | 
					
						
							| 
									
										
										
										
											2022-11-11 12:18:38 +01:00
										 |  |  | 			return nil, deref_ptr_rmangler(rmng, count) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return nil, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Try remove a layer of derefs by loading a mangler | 
					
						
							|  |  |  | 	// for a known ptr kind. The less reflection the better! | 
					
						
							|  |  |  | 	if mng := loadReflectKnownPtr(et); mng != nil { | 
					
						
							|  |  |  | 		if count == 1 { | 
					
						
							|  |  |  | 			return mng, nil | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return nil, deref_ptr_mangler(mng, count-1) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Search for ptr elemn type mangler | 
					
						
							|  |  |  | 	if mng, rmng := load(nil, et); mng != nil { | 
					
						
							|  |  |  | 		return nil, deref_ptr_mangler(mng, count) | 
					
						
							|  |  |  | 	} else if rmng != nil { | 
					
						
							|  |  |  | 		return nil, deref_ptr_rmangler(rmng, count) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // loadReflectKnownPtr loads a Mangler function for a known ptr-of-element type (in this case, primtive ptrs). | 
					
						
							|  |  |  | func loadReflectKnownPtr(et reflect.Type) Mangler { | 
					
						
							|  |  |  | 	switch et.Kind() { | 
					
						
							|  |  |  | 	case reflect.String: | 
					
						
							|  |  |  | 		return mangle_string_ptr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.Bool: | 
					
						
							|  |  |  | 		return mangle_bool_ptr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.Int, | 
					
						
							|  |  |  | 		reflect.Uint, | 
					
						
							|  |  |  | 		reflect.Uintptr: | 
					
						
							|  |  |  | 		return mangle_platform_int_ptr | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-06 10:16:09 +00:00
										 |  |  | 	case reflect.Int8, reflect.Uint8: | 
					
						
							| 
									
										
										
										
											2022-11-11 12:18:38 +01:00
										 |  |  | 		return mangle_8bit_ptr | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-06 10:16:09 +00:00
										 |  |  | 	case reflect.Int16, reflect.Uint16: | 
					
						
							| 
									
										
										
										
											2022-11-11 12:18:38 +01:00
										 |  |  | 		return mangle_16bit_ptr | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-06 10:16:09 +00:00
										 |  |  | 	case reflect.Int32, reflect.Uint32: | 
					
						
							| 
									
										
										
										
											2022-11-11 12:18:38 +01:00
										 |  |  | 		return mangle_32bit_ptr | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-06 10:16:09 +00:00
										 |  |  | 	case reflect.Int64, reflect.Uint64: | 
					
						
							| 
									
										
										
										
											2022-11-11 12:18:38 +01:00
										 |  |  | 		return mangle_64bit_ptr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.Float32: | 
					
						
							|  |  |  | 		return mangle_32bit_ptr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.Float64: | 
					
						
							|  |  |  | 		return mangle_64bit_ptr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.Complex64: | 
					
						
							|  |  |  | 		return mangle_64bit_ptr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.Complex128: | 
					
						
							|  |  |  | 		return mangle_128bit_ptr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // loadReflectKnownSlice loads a Mangler function for a known slice-of-element type (in this case, primtives). | 
					
						
							|  |  |  | func loadReflectKnownSlice(et reflect.Type) Mangler { | 
					
						
							|  |  |  | 	switch et.Kind() { | 
					
						
							|  |  |  | 	case reflect.String: | 
					
						
							|  |  |  | 		return mangle_string_slice | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.Bool: | 
					
						
							|  |  |  | 		return mangle_bool_slice | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.Int, | 
					
						
							|  |  |  | 		reflect.Uint, | 
					
						
							|  |  |  | 		reflect.Uintptr: | 
					
						
							|  |  |  | 		return mangle_platform_int_slice | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-06 10:16:09 +00:00
										 |  |  | 	case reflect.Int8, reflect.Uint8: | 
					
						
							| 
									
										
										
										
											2022-11-11 12:18:38 +01:00
										 |  |  | 		return mangle_8bit_slice | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-06 10:16:09 +00:00
										 |  |  | 	case reflect.Int16, reflect.Uint16: | 
					
						
							| 
									
										
										
										
											2022-11-11 12:18:38 +01:00
										 |  |  | 		return mangle_16bit_slice | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-06 10:16:09 +00:00
										 |  |  | 	case reflect.Int32, reflect.Uint32: | 
					
						
							| 
									
										
										
										
											2022-11-11 12:18:38 +01:00
										 |  |  | 		return mangle_32bit_slice | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-06 10:16:09 +00:00
										 |  |  | 	case reflect.Int64, reflect.Uint64: | 
					
						
							| 
									
										
										
										
											2022-11-11 12:18:38 +01:00
										 |  |  | 		return mangle_64bit_slice | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.Float32: | 
					
						
							|  |  |  | 		return mangle_32bit_slice | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.Float64: | 
					
						
							|  |  |  | 		return mangle_64bit_slice | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.Complex64: | 
					
						
							|  |  |  | 		return mangle_64bit_slice | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.Complex128: | 
					
						
							|  |  |  | 		return mangle_128bit_slice | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // loadReflectArray loads an rMangler function for an array (or slice) or given element type. | 
					
						
							|  |  |  | func loadReflectArray(et reflect.Type) rMangler { | 
					
						
							|  |  |  | 	// Search via reflected array element type | 
					
						
							|  |  |  | 	if mng, rmng := load(nil, et); mng != nil { | 
					
						
							|  |  |  | 		return iter_array_mangler(mng) | 
					
						
							|  |  |  | 	} else if rmng != nil { | 
					
						
							|  |  |  | 		return iter_array_rmangler(rmng) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-06 10:16:09 +00:00
										 |  |  | // loadReflectMap loads an rMangler function for a map of given key and value types. | 
					
						
							| 
									
										
										
										
											2022-11-11 12:18:38 +01:00
										 |  |  | func loadReflectMap(kt, vt reflect.Type) rMangler { | 
					
						
							|  |  |  | 	var kmng, vmng rMangler | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Search for mangler for key type | 
					
						
							|  |  |  | 	mng, rmng := load(nil, kt) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch { | 
					
						
							|  |  |  | 	// Wrap key mangler to reflect | 
					
						
							|  |  |  | 	case mng != nil: | 
					
						
							|  |  |  | 		mng := mng // take our own ptr | 
					
						
							|  |  |  | 		kmng = func(buf []byte, v reflect.Value) []byte { | 
					
						
							|  |  |  | 			return mng(buf, v.Interface()) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Use reflect key mangler as-is | 
					
						
							|  |  |  | 	case rmng != nil: | 
					
						
							|  |  |  | 		kmng = rmng | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// No mangler found | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Search for mangler for value type | 
					
						
							|  |  |  | 	mng, rmng = load(nil, vt) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch { | 
					
						
							| 
									
										
										
										
											2023-02-19 09:36:38 +00:00
										 |  |  | 	// Wrap value mangler to reflect | 
					
						
							| 
									
										
										
										
											2022-11-11 12:18:38 +01:00
										 |  |  | 	case mng != nil: | 
					
						
							|  |  |  | 		mng := mng // take our own ptr | 
					
						
							|  |  |  | 		vmng = func(buf []byte, v reflect.Value) []byte { | 
					
						
							|  |  |  | 			return mng(buf, v.Interface()) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-19 09:36:38 +00:00
										 |  |  | 	// Use reflect value mangler as-is | 
					
						
							| 
									
										
										
										
											2022-11-11 12:18:38 +01:00
										 |  |  | 	case rmng != nil: | 
					
						
							|  |  |  | 		vmng = rmng | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// No mangler found | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Wrap key/value manglers in map iter | 
					
						
							|  |  |  | 	return iter_map_rmangler(kmng, vmng) | 
					
						
							|  |  |  | } |