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(t reflect.Type) Mangler { ctx := typecontext{rtype: t} // Load mangler fn mng := load(ctx) 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. func load(ctx typecontext) Mangler { if ctx.rtype == nil { // There is no reflect type to search by panic("cannot mangle nil interface{} type") } // Search by reflection. mng := loadReflect(ctx) 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. func loadReflect(ctx typecontext) Mangler { switch ctx.rtype.Kind() { case reflect.Pointer: return loadReflectPtr(ctx) case reflect.String: return mangle_string case reflect.Struct: return loadReflectStruct(ctx) case reflect.Array: return loadReflectArray(ctx) case reflect.Slice: return loadReflectSlice(ctx) case reflect.Bool: return mangle_bool case reflect.Int, reflect.Uint, reflect.Uintptr: return mangle_int 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). func loadReflectPtr(ctx typecontext) Mangler { var n uint // Iteratively dereference ptrs for ctx.rtype.Kind() == reflect.Pointer { ctx.rtype = ctx.rtype.Elem() n++ } // Search for elemn type mangler. if mng := load(ctx); mng != nil { return deref_ptr_mangler(ctx, mng, n) } return nil } // loadReflectKnownSlice loads a Mangler function for a // known slice-of-element type (in this case, primtives). func loadReflectKnownSlice(ctx typecontext) Mangler { switch ctx.rtype.Kind() { case reflect.String: return mangle_string_slice case reflect.Bool: return mangle_bool_slice case reflect.Int, reflect.Uint, reflect.Uintptr: return mangle_int_slice 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 ... func loadReflectSlice(ctx typecontext) Mangler { // Set nesting type. ctx.ntype = ctx.rtype // Get nested element type. ctx.rtype = ctx.rtype.Elem() // Preferably look for known slice mangler func if mng := loadReflectKnownSlice(ctx); mng != nil { return mng } // Use nested mangler iteration. if mng := load(ctx); mng != nil { return iter_slice_mangler(ctx, mng) } return nil } // loadReflectArray ... func loadReflectArray(ctx typecontext) Mangler { // Set nesting type. ctx.ntype = ctx.rtype // Get nested element type. ctx.rtype = ctx.rtype.Elem() // Use manglers for nested iteration. if mng := load(ctx); mng != nil { return iter_array_mangler(ctx, mng) } return nil } // loadReflectStruct ... func loadReflectStruct(ctx typecontext) Mangler { var mngs []Mangler // Set nesting type. ctx.ntype = ctx.rtype // Gather manglers for all fields. for i := 0; i < ctx.ntype.NumField(); i++ { // Field typectx. ctx := typecontext{ ntype: ctx.ntype, rtype: ctx.ntype.Field(i).Type, } // Load mangler. mng := load(ctx) if mng == nil { return nil } // Append next to map. mngs = append(mngs, mng) } // Use manglers for nested iteration. return iter_struct_mangler(ctx, mngs) }