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  }