github.com/wangyougui/gf/v2@v2.6.5/util/gconv/gconv.go (about)

     1  // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the MIT License.
     4  // If a copy of the MIT was not distributed with this file,
     5  // You can obtain one at https://github.com/wangyougui/gf.
     6  
     7  // Package gconv implements powerful and convenient converting functionality for any types of variables.
     8  //
     9  // This package should keep much less dependencies with other packages.
    10  package gconv
    11  
    12  import (
    13  	"context"
    14  	"fmt"
    15  	"math"
    16  	"reflect"
    17  	"strconv"
    18  	"strings"
    19  	"time"
    20  
    21  	"github.com/wangyougui/gf/v2/encoding/gbinary"
    22  	"github.com/wangyougui/gf/v2/internal/intlog"
    23  	"github.com/wangyougui/gf/v2/internal/json"
    24  	"github.com/wangyougui/gf/v2/internal/reflection"
    25  	"github.com/wangyougui/gf/v2/os/gtime"
    26  	"github.com/wangyougui/gf/v2/util/gtag"
    27  )
    28  
    29  var (
    30  	// Empty strings.
    31  	emptyStringMap = map[string]struct{}{
    32  		"":      {},
    33  		"0":     {},
    34  		"no":    {},
    35  		"off":   {},
    36  		"false": {},
    37  	}
    38  
    39  	// StructTagPriority defines the default priority tags for Map*/Struct* functions.
    40  	// Note that, the `gconv/param` tags are used by old version of package.
    41  	// It is strongly recommended using short tag `c/p` instead in the future.
    42  	StructTagPriority = gtag.StructTagPriority
    43  )
    44  
    45  // Byte converts `any` to byte.
    46  func Byte(any interface{}) byte {
    47  	if v, ok := any.(byte); ok {
    48  		return v
    49  	}
    50  	return Uint8(any)
    51  }
    52  
    53  // Bytes converts `any` to []byte.
    54  func Bytes(any interface{}) []byte {
    55  	if any == nil {
    56  		return nil
    57  	}
    58  	switch value := any.(type) {
    59  	case string:
    60  		return []byte(value)
    61  
    62  	case []byte:
    63  		return value
    64  
    65  	default:
    66  		if f, ok := value.(iBytes); ok {
    67  			return f.Bytes()
    68  		}
    69  		originValueAndKind := reflection.OriginValueAndKind(any)
    70  		switch originValueAndKind.OriginKind {
    71  		case reflect.Map:
    72  			bytes, err := json.Marshal(any)
    73  			if err != nil {
    74  				intlog.Errorf(context.TODO(), `%+v`, err)
    75  			}
    76  			return bytes
    77  
    78  		case reflect.Array, reflect.Slice:
    79  			var (
    80  				ok    = true
    81  				bytes = make([]byte, originValueAndKind.OriginValue.Len())
    82  			)
    83  			for i := range bytes {
    84  				int32Value := Int32(originValueAndKind.OriginValue.Index(i).Interface())
    85  				if int32Value < 0 || int32Value > math.MaxUint8 {
    86  					ok = false
    87  					break
    88  				}
    89  				bytes[i] = byte(int32Value)
    90  			}
    91  			if ok {
    92  				return bytes
    93  			}
    94  		}
    95  		return gbinary.Encode(any)
    96  	}
    97  }
    98  
    99  // Rune converts `any` to rune.
   100  func Rune(any interface{}) rune {
   101  	if v, ok := any.(rune); ok {
   102  		return v
   103  	}
   104  	return Int32(any)
   105  }
   106  
   107  // Runes converts `any` to []rune.
   108  func Runes(any interface{}) []rune {
   109  	if v, ok := any.([]rune); ok {
   110  		return v
   111  	}
   112  	return []rune(String(any))
   113  }
   114  
   115  // String converts `any` to string.
   116  // It's most commonly used converting function.
   117  func String(any interface{}) string {
   118  	if any == nil {
   119  		return ""
   120  	}
   121  	switch value := any.(type) {
   122  	case int:
   123  		return strconv.Itoa(value)
   124  	case int8:
   125  		return strconv.Itoa(int(value))
   126  	case int16:
   127  		return strconv.Itoa(int(value))
   128  	case int32:
   129  		return strconv.Itoa(int(value))
   130  	case int64:
   131  		return strconv.FormatInt(value, 10)
   132  	case uint:
   133  		return strconv.FormatUint(uint64(value), 10)
   134  	case uint8:
   135  		return strconv.FormatUint(uint64(value), 10)
   136  	case uint16:
   137  		return strconv.FormatUint(uint64(value), 10)
   138  	case uint32:
   139  		return strconv.FormatUint(uint64(value), 10)
   140  	case uint64:
   141  		return strconv.FormatUint(value, 10)
   142  	case float32:
   143  		return strconv.FormatFloat(float64(value), 'f', -1, 32)
   144  	case float64:
   145  		return strconv.FormatFloat(value, 'f', -1, 64)
   146  	case bool:
   147  		return strconv.FormatBool(value)
   148  	case string:
   149  		return value
   150  	case []byte:
   151  		return string(value)
   152  	case time.Time:
   153  		if value.IsZero() {
   154  			return ""
   155  		}
   156  		return value.String()
   157  	case *time.Time:
   158  		if value == nil {
   159  			return ""
   160  		}
   161  		return value.String()
   162  	case gtime.Time:
   163  		if value.IsZero() {
   164  			return ""
   165  		}
   166  		return value.String()
   167  	case *gtime.Time:
   168  		if value == nil {
   169  			return ""
   170  		}
   171  		return value.String()
   172  	default:
   173  		// Empty checks.
   174  		if value == nil {
   175  			return ""
   176  		}
   177  		if f, ok := value.(iString); ok {
   178  			// If the variable implements the String() interface,
   179  			// then use that interface to perform the conversion
   180  			return f.String()
   181  		}
   182  		if f, ok := value.(iError); ok {
   183  			// If the variable implements the Error() interface,
   184  			// then use that interface to perform the conversion
   185  			return f.Error()
   186  		}
   187  		// Reflect checks.
   188  		var (
   189  			rv   = reflect.ValueOf(value)
   190  			kind = rv.Kind()
   191  		)
   192  		switch kind {
   193  		case reflect.Chan,
   194  			reflect.Map,
   195  			reflect.Slice,
   196  			reflect.Func,
   197  			reflect.Ptr,
   198  			reflect.Interface,
   199  			reflect.UnsafePointer:
   200  			if rv.IsNil() {
   201  				return ""
   202  			}
   203  		case reflect.String:
   204  			return rv.String()
   205  		}
   206  		if kind == reflect.Ptr {
   207  			return String(rv.Elem().Interface())
   208  		}
   209  		// Finally, we use json.Marshal to convert.
   210  		if jsonContent, err := json.Marshal(value); err != nil {
   211  			return fmt.Sprint(value)
   212  		} else {
   213  			return string(jsonContent)
   214  		}
   215  	}
   216  }
   217  
   218  // Bool converts `any` to bool.
   219  // It returns false if `any` is: false, "", 0, "false", "off", "no", empty slice/map.
   220  func Bool(any interface{}) bool {
   221  	if any == nil {
   222  		return false
   223  	}
   224  	switch value := any.(type) {
   225  	case bool:
   226  		return value
   227  	case []byte:
   228  		if _, ok := emptyStringMap[strings.ToLower(string(value))]; ok {
   229  			return false
   230  		}
   231  		return true
   232  	case string:
   233  		if _, ok := emptyStringMap[strings.ToLower(value)]; ok {
   234  			return false
   235  		}
   236  		return true
   237  	default:
   238  		if f, ok := value.(iBool); ok {
   239  			return f.Bool()
   240  		}
   241  		rv := reflect.ValueOf(any)
   242  		switch rv.Kind() {
   243  		case reflect.Ptr:
   244  			return !rv.IsNil()
   245  		case reflect.Map:
   246  			fallthrough
   247  		case reflect.Array:
   248  			fallthrough
   249  		case reflect.Slice:
   250  			return rv.Len() != 0
   251  		case reflect.Struct:
   252  			return true
   253  		default:
   254  			s := strings.ToLower(String(any))
   255  			if _, ok := emptyStringMap[s]; ok {
   256  				return false
   257  			}
   258  			return true
   259  		}
   260  	}
   261  }
   262  
   263  // checkJsonAndUnmarshalUseNumber checks if given `any` is JSON formatted string value and does converting using `json.UnmarshalUseNumber`.
   264  func checkJsonAndUnmarshalUseNumber(any interface{}, target interface{}) bool {
   265  	switch r := any.(type) {
   266  	case []byte:
   267  		if json.Valid(r) {
   268  			if err := json.UnmarshalUseNumber(r, &target); err != nil {
   269  				return false
   270  			}
   271  			return true
   272  		}
   273  
   274  	case string:
   275  		anyAsBytes := []byte(r)
   276  		if json.Valid(anyAsBytes) {
   277  			if err := json.UnmarshalUseNumber(anyAsBytes, &target); err != nil {
   278  				return false
   279  			}
   280  			return true
   281  		}
   282  	}
   283  	return false
   284  }