| 
									
										
										
										
											2024-04-02 11:03:40 +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. | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | func loadMangler(t reflect.Type) Mangler { | 
					
						
							|  |  |  | 	ctx := typecontext{rtype: t} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 	// Load mangler fn | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | 	mng := load(ctx) | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 	if mng != nil { | 
					
						
							|  |  |  | 		return mng | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// No mangler function could be determined | 
					
						
							|  |  |  | 	panic("cannot mangle type: " + t.String()) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // 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. | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | func load(ctx typecontext) Mangler { | 
					
						
							|  |  |  | 	if ctx.rtype == nil { | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 		// There is no reflect type to search by | 
					
						
							|  |  |  | 		panic("cannot mangle nil interface{} type") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | 	// Search by reflection. | 
					
						
							|  |  |  | 	mng := loadReflect(ctx) | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 	if mng != nil { | 
					
						
							|  |  |  | 		return mng | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	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. | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | func loadReflect(ctx typecontext) Mangler { | 
					
						
							|  |  |  | 	switch ctx.rtype.Kind() { | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 	case reflect.Pointer: | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | 		return loadReflectPtr(ctx) | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.String: | 
					
						
							|  |  |  | 		return mangle_string | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.Struct: | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | 		return loadReflectStruct(ctx) | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.Array: | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | 		return loadReflectArray(ctx) | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.Slice: | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | 		return loadReflectSlice(ctx) | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.Bool: | 
					
						
							|  |  |  | 		return mangle_bool | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.Int, | 
					
						
							|  |  |  | 		reflect.Uint, | 
					
						
							|  |  |  | 		reflect.Uintptr: | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | 		return mangle_int | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.Int8, reflect.Uint8: | 
					
						
							|  |  |  | 		return mangle_8bit | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.Int16, reflect.Uint16: | 
					
						
							|  |  |  | 		return mangle_16bit | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.Int32, reflect.Uint32: | 
					
						
							|  |  |  | 		return mangle_32bit | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.Int64, reflect.Uint64: | 
					
						
							|  |  |  | 		return mangle_64bit | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.Float32: | 
					
						
							|  |  |  | 		return mangle_32bit | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.Float64: | 
					
						
							|  |  |  | 		return mangle_64bit | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.Complex64: | 
					
						
							|  |  |  | 		return mangle_64bit | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.Complex128: | 
					
						
							|  |  |  | 		return mangle_128bit | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		return 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). | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | func loadReflectPtr(ctx typecontext) Mangler { | 
					
						
							|  |  |  | 	var n uint | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Iteratively dereference ptrs | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | 	for ctx.rtype.Kind() == reflect.Pointer { | 
					
						
							|  |  |  | 		ctx.rtype = ctx.rtype.Elem() | 
					
						
							|  |  |  | 		n++ | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | 	// Search for elemn type mangler. | 
					
						
							|  |  |  | 	if mng := load(ctx); mng != nil { | 
					
						
							|  |  |  | 		return deref_ptr_mangler(ctx, mng, n) | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // loadReflectKnownSlice loads a Mangler function for a | 
					
						
							|  |  |  | // known slice-of-element type (in this case, primtives). | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | func loadReflectKnownSlice(ctx typecontext) Mangler { | 
					
						
							|  |  |  | 	switch ctx.rtype.Kind() { | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 	case reflect.String: | 
					
						
							|  |  |  | 		return mangle_string_slice | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.Bool: | 
					
						
							|  |  |  | 		return mangle_bool_slice | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.Int, | 
					
						
							|  |  |  | 		reflect.Uint, | 
					
						
							|  |  |  | 		reflect.Uintptr: | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | 		return mangle_int_slice | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.Int8, reflect.Uint8: | 
					
						
							|  |  |  | 		return mangle_8bit_slice | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.Int16, reflect.Uint16: | 
					
						
							|  |  |  | 		return mangle_16bit_slice | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.Int32, reflect.Uint32: | 
					
						
							|  |  |  | 		return mangle_32bit_slice | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case reflect.Int64, reflect.Uint64: | 
					
						
							|  |  |  | 		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 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // loadReflectSlice ... | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | func loadReflectSlice(ctx typecontext) Mangler { | 
					
						
							|  |  |  | 	// Set nesting type. | 
					
						
							|  |  |  | 	ctx.ntype = ctx.rtype | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Get nested element type. | 
					
						
							|  |  |  | 	ctx.rtype = ctx.rtype.Elem() | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Preferably look for known slice mangler func | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | 	if mng := loadReflectKnownSlice(ctx); mng != nil { | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 		return mng | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | 	// Use nested mangler iteration. | 
					
						
							|  |  |  | 	if mng := load(ctx); mng != nil { | 
					
						
							|  |  |  | 		return iter_slice_mangler(ctx, mng) | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // loadReflectArray ... | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | func loadReflectArray(ctx typecontext) Mangler { | 
					
						
							|  |  |  | 	// Set nesting type. | 
					
						
							|  |  |  | 	ctx.ntype = ctx.rtype | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | 	// Get nested element type. | 
					
						
							|  |  |  | 	ctx.rtype = ctx.rtype.Elem() | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Use manglers for nested iteration. | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | 	if mng := load(ctx); mng != nil { | 
					
						
							|  |  |  | 		return iter_array_mangler(ctx, mng) | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // loadReflectStruct ... | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | func loadReflectStruct(ctx typecontext) Mangler { | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 	var mngs []Mangler | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | 	// Set nesting type. | 
					
						
							|  |  |  | 	ctx.ntype = ctx.rtype | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 	// Gather manglers for all fields. | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | 	for i := 0; i < ctx.ntype.NumField(); i++ { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Field typectx. | 
					
						
							|  |  |  | 		ctx := typecontext{ | 
					
						
							|  |  |  | 			ntype: ctx.ntype, | 
					
						
							|  |  |  | 			rtype: ctx.ntype.Field(i).Type, | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | 		// Load mangler. | 
					
						
							|  |  |  | 		mng := load(ctx) | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | 		if mng == nil { | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Append next to map. | 
					
						
							|  |  |  | 		mngs = append(mngs, mng) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Use manglers for nested iteration. | 
					
						
							| 
									
										
										
										
											2024-06-21 15:43:17 +00:00
										 |  |  | 	return iter_struct_mangler(ctx, mngs) | 
					
						
							| 
									
										
										
										
											2024-04-02 11:03:40 +01:00
										 |  |  | } |