123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 |
- package valid
- import (
- "database/sql/driver"
- "errors"
- "fmt"
- "reflect"
- "strings"
- "time"
- )
- var (
- bytesType = reflect.TypeOf([]byte(nil))
- valuerType = reflect.TypeOf((*driver.Valuer)(nil)).Elem()
- // ErrEnsureString is the error that returns when a value is not a string or byte slice.
- ErrEnsureString = errors.New("must be either a string or byte slice")
- )
- // EnsureString ensures the given value is a string.
- // If the value is a byte slice, it will be typecast into a string.
- // An error is returned otherwise.
- func EnsureString(value interface{}) (string, error) {
- v := reflect.ValueOf(value)
- if v.Kind() == reflect.String {
- return v.String(), nil
- }
- if v.Type() == bytesType {
- return string(v.Interface().([]byte)), nil
- }
- return "", ErrEnsureString
- }
- // IsBlankString check the given value is a empty values or whitespace only values
- func IsBlankString(value string) bool {
- if value == "" {
- return true
- }
- if strings.TrimSpace(value) == "" {
- return true
- }
- return false
- }
- // StringOrBytes typecasts a value into a string or byte slice.
- // Boolean flags are returned to indicate if the typecasting succeeds or not.
- func StringOrBytes(value interface{}) (isString bool, str string, isBytes bool, bs []byte) {
- v := reflect.ValueOf(value)
- if v.Kind() == reflect.String {
- str = v.String()
- isString = true
- } else if v.Kind() == reflect.Slice && v.Type() == bytesType {
- bs = v.Interface().([]byte)
- isBytes = true
- }
- return
- }
- // LengthOfValue returns the length of a value that is a string, slice, map, or array.
- // An error is returned for all other types.
- func LengthOfValue(value interface{}) (int, error) {
- v := reflect.ValueOf(value)
- switch v.Kind() {
- case reflect.String, reflect.Slice, reflect.Map, reflect.Array:
- return v.Len(), nil
- }
- return 0, fmt.Errorf("cannot get the length of %v", v.Kind())
- }
- // ToInt converts the given value to an int64.
- // An error is returned for all incompatible types.
- func ToInt(value interface{}) (int64, error) {
- v := reflect.ValueOf(value)
- switch v.Kind() {
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- return v.Int(), nil
- }
- return 0, fmt.Errorf("cannot convert %v to int64", v.Kind())
- }
- // ToUint converts the given value to an uint64.
- // An error is returned for all incompatible types.
- func ToUint(value interface{}) (uint64, error) {
- v := reflect.ValueOf(value)
- switch v.Kind() {
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
- return v.Uint(), nil
- }
- return 0, fmt.Errorf("cannot convert %v to uint64", v.Kind())
- }
- // ToFloat converts the given value to a float64.
- // An error is returned for all incompatible types.
- func ToFloat(value interface{}) (float64, error) {
- v := reflect.ValueOf(value)
- switch v.Kind() {
- case reflect.Float32, reflect.Float64:
- return v.Float(), nil
- }
- return 0, fmt.Errorf("cannot convert %v to float64", v.Kind())
- }
- // IsEmpty checks if a value is empty or not.
- // A value is considered empty if
- // - integer, float: zero
- // - bool: false
- // - string, array: len() == 0
- // - slice, map: nil or len() == 0
- // - interface, pointer: nil or the referenced value is empty
- func IsEmpty(value interface{}) bool {
- v := reflect.ValueOf(value)
- switch v.Kind() {
- case reflect.String, reflect.Array, reflect.Map, reflect.Slice:
- return v.Len() == 0
- case reflect.Bool:
- return !v.Bool()
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- return v.Int() == 0
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
- return v.Uint() == 0
- case reflect.Float32, reflect.Float64:
- return v.Float() == 0
- case reflect.Invalid:
- return true
- case reflect.Interface, reflect.Ptr:
- if v.IsNil() {
- return true
- }
- return IsEmpty(v.Elem().Interface())
- case reflect.Struct:
- v, ok := value.(time.Time)
- if ok && v.IsZero() {
- return true
- }
- }
- return false
- }
- // Indirect returns the value that the given interface or pointer references to.
- // If the value implements driver.Valuer, it will deal with the value returned by
- // the Value() method instead. A boolean value is also returned to indicate if
- // the value is nil or not (only applicable to interface, pointer, map, and slice).
- // If the value is neither an interface nor a pointer, it will be returned back.
- func Indirect(value interface{}) (interface{}, bool) {
- rv := reflect.ValueOf(value)
- kind := rv.Kind()
- switch kind {
- case reflect.Invalid:
- return nil, true
- case reflect.Ptr, reflect.Interface:
- if rv.IsNil() {
- return nil, true
- }
- return Indirect(rv.Elem().Interface())
- case reflect.Slice, reflect.Map, reflect.Func, reflect.Chan:
- if rv.IsNil() {
- return nil, true
- }
- }
- if rv.Type().Implements(valuerType) {
- return indirectValuer(value.(driver.Valuer))
- }
- return value, false
- }
- func indirectValuer(valuer driver.Valuer) (interface{}, bool) {
- if value, err := valuer.Value(); value != nil && err == nil {
- return Indirect(value)
- }
- return nil, true
- }
|