From d35a16ec64f579a02b0f7f917b09fdb8bd740233 Mon Sep 17 00:00:00 2001 From: Arsen Musayelyan Date: Sat, 6 Aug 2022 22:49:12 -0700 Subject: [PATCH] Remove now useless internal/reflectutil --- internal/reflectutil/utils.go | 188 ---------------------------------- 1 file changed, 188 deletions(-) delete mode 100644 internal/reflectutil/utils.go diff --git a/internal/reflectutil/utils.go b/internal/reflectutil/utils.go deleted file mode 100644 index 496b646..0000000 --- a/internal/reflectutil/utils.go +++ /dev/null @@ -1,188 +0,0 @@ -/* - * lrpc allows for clients to call functions on a server remotely. - * Copyright (C) 2022 Arsen Musayelyan - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package reflectutil - -import ( - "encoding" - "fmt" - "reflect" - - "github.com/mitchellh/mapstructure" -) - -// <= go1.17 compatibility -type any = interface{} - -// Convert attempts to convert the given value to the given type -func Convert(in reflect.Value, toType reflect.Type) (reflect.Value, error) { - // Get input type - inType := in.Type() - - // If input is already the desired type, return - if inType == toType { - return in, nil - } - - // If the output type is a pointer to the input type - if reflect.PtrTo(inType) == toType { - if in.CanAddr() { - // Return pointer to input - return in.Addr(), nil - } - - inPtrVal := reflect.New(inType) - inPtrVal.Elem().Set(in) - return inPtrVal, nil - } - - // If input is a pointer pointing to the output type - if inType.Kind() == reflect.Ptr && inType.Elem() == toType { - // Return value being pointed at by input - return reflect.Indirect(in), nil - } - - // If input can be converted to desired type, convert and return - if in.CanConvert(toType) { - return in.Convert(toType), nil - } - - // Create new value of desired type - to := reflect.New(toType).Elem() - - // If type is a pointer - if to.Kind() == reflect.Ptr { - // Initialize value - to.Set(reflect.New(to.Type().Elem())) - } - - switch val := in.Interface().(type) { - case string: - // If desired type satisfies text unmarshaler - if u, ok := to.Interface().(encoding.TextUnmarshaler); ok { - // Use text unmarshaler to get value - err := u.UnmarshalText([]byte(val)) - if err != nil { - return reflect.Value{}, err - } - - // Return unmarshaled value - return reflect.ValueOf(any(u)), nil - } - case []byte: - // If desired type satisfies binary unmarshaler - if u, ok := to.Interface().(encoding.BinaryUnmarshaler); ok { - // Use binary unmarshaler to get value - err := u.UnmarshalBinary(val) - if err != nil { - return reflect.Value{}, err - } - - // Return unmarshaled value - return reflect.ValueOf(any(u)), nil - } - } - - // If input is a map - if in.Kind() == reflect.Map { - // Use mapstructure to decode value - err := mapstructure.Decode(in.Interface(), to.Addr().Interface()) - if err == nil { - return to, nil - } else { - return reflect.Value{}, err - } - } - - // If input is a slice of any, and output is an array or slice - if in.Type() == reflect.TypeOf([]any{}) && - (to.Kind() == reflect.Slice || to.Kind() == reflect.Array) { - // Use ConvertSlice to convert value - return reflect.ValueOf(ConvertSlice( - in.Interface().([]any), - toType, - )), nil - } - - return to, fmt.Errorf("cannot convert %s to %s", inType, toType) -} - -// ConvertSlice converts []any to an array or slice, as provided -// in the "to" argument. -func ConvertSlice(in []any, to reflect.Type) any { - // Create new value for output - out := reflect.New(to).Elem() - - // Get type of slice elements - outType := out.Type().Elem() - - // If output value is a slice - if out.Kind() == reflect.Slice { - // For every value provided - for i := 0; i < len(in); i++ { - // Get value of input type - inVal := reflect.ValueOf(in[i]) - // Create new output type - outVal := reflect.New(outType).Elem() - - // If types match - if inVal.Type() == outType { - // Set output value to input value - outVal.Set(inVal) - } else { - newVal, err := Convert(inVal, outType) - if err != nil { - // Set output value to its zero value - outVal.Set(reflect.Zero(outVal.Type())) - } else { - outVal.Set(newVal) - } - } - - // Append output value to slice - out = reflect.Append(out, outVal) - } - } else if out.Kind() == reflect.Array && out.Len() == len(in) { - //If output type is array and lengths match - - // For every input value - for i := 0; i < len(in); i++ { - // Get matching output index - outVal := out.Index(i) - // Get input value - inVal := reflect.ValueOf(in[i]) - - // If types match - if inVal.Type() == outVal.Type() { - // Set output value to input value - outVal.Set(inVal) - } else { - newVal, err := Convert(inVal, outType) - if err != nil { - // Set output value to its zero value - outVal.Set(reflect.Zero(outVal.Type())) - } else { - outVal.Set(newVal) - } - } - } - } - - // Return created value - return out.Interface() -}