github.com/kaydxh/golang@v0.0.131/go/reflect/value.go (about)

     1  /*
     2   *Copyright (c) 2022, kaydxh
     3   *
     4   *Permission is hereby granted, free of charge, to any person obtaining a copy
     5   *of this software and associated documentation files (the "Software"), to deal
     6   *in the Software without restriction, including without limitation the rights
     7   *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     8   *copies of the Software, and to permit persons to whom the Software is
     9   *furnished to do so, subject to the following conditions:
    10   *
    11   *The above copyright notice and this permission notice shall be included in all
    12   *copies or substantial portions of the Software.
    13   *
    14   *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    15   *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    16   *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    17   *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    18   *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    19   *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    20   *SOFTWARE.
    21   */
    22  package reflect
    23  
    24  import (
    25  	"context"
    26  	"encoding/json"
    27  	"fmt"
    28  	"math"
    29  	"reflect"
    30  	"strings"
    31  )
    32  
    33  var (
    34  	typesMap = map[string]reflect.Type{
    35  		// base types
    36  		"bool":    reflect.TypeOf(true),
    37  		"int":     reflect.TypeOf(int(1)),
    38  		"int8":    reflect.TypeOf(int8(1)),
    39  		"int16":   reflect.TypeOf(int16(1)),
    40  		"int32":   reflect.TypeOf(int32(1)),
    41  		"int64":   reflect.TypeOf(int64(1)),
    42  		"uint":    reflect.TypeOf(uint(1)),
    43  		"uint8":   reflect.TypeOf(uint8(1)),
    44  		"uint16":  reflect.TypeOf(uint16(1)),
    45  		"uint32":  reflect.TypeOf(uint32(1)),
    46  		"uint64":  reflect.TypeOf(uint64(1)),
    47  		"float32": reflect.TypeOf(float32(0.5)),
    48  		"float64": reflect.TypeOf(float64(0.5)),
    49  		"string":  reflect.TypeOf(string("")),
    50  		// slices
    51  		"[]bool":    reflect.TypeOf(make([]bool, 0)),
    52  		"[]int":     reflect.TypeOf(make([]int, 0)),
    53  		"[]int8":    reflect.TypeOf(make([]int8, 0)),
    54  		"[]int16":   reflect.TypeOf(make([]int16, 0)),
    55  		"[]int32":   reflect.TypeOf(make([]int32, 0)),
    56  		"[]int64":   reflect.TypeOf(make([]int64, 0)),
    57  		"[]uint":    reflect.TypeOf(make([]uint, 0)),
    58  		"[]uint8":   reflect.TypeOf(make([]uint8, 0)),
    59  		"[]uint16":  reflect.TypeOf(make([]uint16, 0)),
    60  		"[]uint32":  reflect.TypeOf(make([]uint32, 0)),
    61  		"[]uint64":  reflect.TypeOf(make([]uint64, 0)),
    62  		"[]float32": reflect.TypeOf(make([]float32, 0)),
    63  		"[]float64": reflect.TypeOf(make([]float64, 0)),
    64  		"[]byte":    reflect.TypeOf(make([]byte, 0)),
    65  		"[]string":  reflect.TypeOf([]string{""}),
    66  	}
    67  
    68  	ctxType = reflect.TypeOf((*context.Context)(nil)).Elem()
    69  
    70  	typeConversionError = func(argValue interface{}, argTypeStr string) error {
    71  		return fmt.Errorf("%v is not %v", argValue, argTypeStr)
    72  	}
    73  )
    74  
    75  // cmd/compile/internal/gc/dump.go
    76  func IsZeroValue(v reflect.Value) bool {
    77  	if !v.IsValid() {
    78  		return true
    79  	}
    80  
    81  	switch v.Kind() {
    82  	case reflect.Bool:
    83  		return !v.Bool()
    84  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
    85  		return v.Int() == 0
    86  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
    87  		return v.Uint() == 0
    88  	case reflect.Float32, reflect.Float64:
    89  		return math.Float64bits(v.Float()) == 0
    90  	case reflect.Complex64, reflect.Complex128:
    91  		c := v.Complex()
    92  		return math.Float64bits(real(c)) == 0 && math.Float64bits(imag(c)) == 0
    93  	case reflect.String:
    94  		return v.String() == ""
    95  	case reflect.Array:
    96  		for i := 0; i < v.Len(); i++ {
    97  			if !v.Index(i).IsZero() {
    98  				return false
    99  			}
   100  		}
   101  		return true
   102  	case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice, reflect.UnsafePointer:
   103  		return v.IsNil()
   104  	case reflect.Struct:
   105  		for i := 0; i < v.NumField(); i++ {
   106  			if !v.Field(i).IsZero() {
   107  				return false
   108  			}
   109  		}
   110  		return true
   111  	default:
   112  	}
   113  
   114  	return reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface())
   115  }
   116  
   117  // ReflectValue converts interface{} to reflect.Value based on string type
   118  func ReflectValue(valueType string, value interface{}) (reflect.Value, error) {
   119  	/*
   120  		if strings.HasPrefix(valueType, "[]") {
   121  			return reflectValues(valueType, value)
   122  		}
   123  	*/
   124  
   125  	return reflectValue(valueType, value)
   126  }
   127  
   128  // reflectValue converts interface{} to reflect.Value based on string type
   129  // representing a base type (not a slice)
   130  func reflectValue(valueType string, value interface{}) (reflect.Value, error) {
   131  	theType, ok := typesMap[valueType]
   132  	if !ok {
   133  		return reflect.Value{}, NewErrUnsupportedType(valueType)
   134  	}
   135  	theValue := reflect.New(theType)
   136  
   137  	// Booleans
   138  	if theType.String() == "bool" {
   139  		boolValue, err := getBoolValue(theType.String(), value)
   140  		if err != nil {
   141  			return reflect.Value{}, err
   142  		}
   143  
   144  		theValue.Elem().SetBool(boolValue)
   145  		return theValue.Elem(), nil
   146  	}
   147  
   148  	// Integers
   149  	if strings.HasPrefix(theType.String(), "int") {
   150  		intValue, err := getIntValue(theType.String(), value)
   151  		if err != nil {
   152  			return reflect.Value{}, err
   153  		}
   154  
   155  		theValue.Elem().SetInt(intValue)
   156  		return theValue.Elem(), err
   157  	}
   158  
   159  	// Unsigned integers
   160  	if strings.HasPrefix(theType.String(), "uint") {
   161  		uintValue, err := getUintValue(theType.String(), value)
   162  		if err != nil {
   163  			return reflect.Value{}, err
   164  		}
   165  
   166  		theValue.Elem().SetUint(uintValue)
   167  		return theValue.Elem(), err
   168  	}
   169  
   170  	// Floating point numbers
   171  	if strings.HasPrefix(theType.String(), "float") {
   172  		floatValue, err := getFloatValue(theType.String(), value)
   173  		if err != nil {
   174  			return reflect.Value{}, err
   175  		}
   176  
   177  		theValue.Elem().SetFloat(floatValue)
   178  		return theValue.Elem(), err
   179  	}
   180  
   181  	// Strings
   182  	if theType.String() == "string" {
   183  		stringValue, err := getStringValue(theType.String(), value)
   184  		if err != nil {
   185  			return reflect.Value{}, err
   186  		}
   187  
   188  		theValue.Elem().SetString(stringValue)
   189  		return theValue.Elem(), nil
   190  	}
   191  
   192  	return reflect.Value{}, NewErrUnsupportedType(valueType)
   193  }
   194  
   195  func getBoolValue(theType string, value interface{}) (bool, error) {
   196  	b, ok := value.(bool)
   197  	if !ok {
   198  		return false, typeConversionError(value, typesMap[theType].String())
   199  	}
   200  
   201  	return b, nil
   202  }
   203  
   204  func getIntValue(theType string, value interface{}) (int64, error) {
   205  	// We use https://golang.org/pkg/encoding/json/#Decoder.UseNumber when unmarshaling signatures.
   206  	// This is because JSON only supports 64-bit floating point numbers and we could lose precision
   207  	// when converting from float64 to signed integer
   208  	if strings.HasPrefix(fmt.Sprintf("%T", value), "json.Number") {
   209  		n, ok := value.(json.Number)
   210  		if !ok {
   211  			return 0, typeConversionError(value, typesMap[theType].String())
   212  		}
   213  
   214  		return n.Int64()
   215  	}
   216  
   217  	var n int64
   218  	switch value := value.(type) {
   219  	case int:
   220  		n = int64(value)
   221  	case int64:
   222  		n = value
   223  	case int32:
   224  		n = int64(value)
   225  	case int16:
   226  		n = int64(value)
   227  	case int8:
   228  		n = int64(value)
   229  	default:
   230  		fmt.Printf("value: %v\n", value)
   231  		return 0, typeConversionError(value, typesMap[theType].String())
   232  	}
   233  
   234  	return n, nil
   235  }
   236  
   237  func getUintValue(theType string, value interface{}) (uint64, error) {
   238  	// We use https://golang.org/pkg/encoding/json/#Decoder.UseNumber when unmarshaling signatures.
   239  	// This is because JSON only supports 64-bit floating point numbers and we could lose precision
   240  	// when converting from float64 to unsigned integer
   241  	if strings.HasPrefix(fmt.Sprintf("%T", value), "json.Number") {
   242  		n, ok := value.(json.Number)
   243  		if !ok {
   244  			fmt.Printf("00000\n")
   245  			return 0, typeConversionError(value, typesMap[theType].String())
   246  		}
   247  
   248  		intVal, err := n.Int64()
   249  		if err != nil {
   250  			return 0, err
   251  		}
   252  
   253  		return uint64(intVal), nil
   254  	}
   255  
   256  	var n uint64
   257  	switch value := value.(type) {
   258  	case uint:
   259  		n = uint64(value)
   260  	case uint64:
   261  		n = value
   262  	case uint32:
   263  		n = uint64(value)
   264  	case uint16:
   265  		n = uint64(value)
   266  	case uint8:
   267  		n = uint64(value)
   268  	default:
   269  		fmt.Printf("value: %v\n", value)
   270  		return 0, typeConversionError(value, typesMap[theType].String())
   271  	}
   272  	return n, nil
   273  }
   274  
   275  func getFloatValue(theType string, value interface{}) (float64, error) {
   276  	// We use https://golang.org/pkg/encoding/json/#Decoder.UseNumber when unmarshaling signatures.
   277  	// This is because JSON only supports 64-bit floating point numbers and we could lose precision
   278  	if strings.HasPrefix(fmt.Sprintf("%T", value), "json.Number") {
   279  		n, ok := value.(json.Number)
   280  		if !ok {
   281  			return 0, typeConversionError(value, typesMap[theType].String())
   282  		}
   283  
   284  		return n.Float64()
   285  	}
   286  
   287  	f, ok := value.(float64)
   288  	if !ok {
   289  		return 0, typeConversionError(value, typesMap[theType].String())
   290  	}
   291  
   292  	return f, nil
   293  }
   294  
   295  func getStringValue(theType string, value interface{}) (string, error) {
   296  	s, ok := value.(string)
   297  	if !ok {
   298  		return "", typeConversionError(value, typesMap[theType].String())
   299  	}
   300  
   301  	return s, nil
   302  }