zerochecker.go (2251B)
1 package schema 2 3 import ( 4 "database/sql/driver" 5 "reflect" 6 ) 7 8 var isZeroerType = reflect.TypeOf((*isZeroer)(nil)).Elem() 9 10 type isZeroer interface { 11 IsZero() bool 12 } 13 14 type IsZeroerFunc func(reflect.Value) bool 15 16 func zeroChecker(typ reflect.Type) IsZeroerFunc { 17 if typ.Implements(isZeroerType) { 18 return isZeroInterface 19 } 20 21 kind := typ.Kind() 22 23 if kind != reflect.Ptr { 24 ptr := reflect.PtrTo(typ) 25 if ptr.Implements(isZeroerType) { 26 return addrChecker(isZeroInterface) 27 } 28 } 29 30 switch kind { 31 case reflect.Array: 32 if typ.Elem().Kind() == reflect.Uint8 { 33 return isZeroBytes 34 } 35 return isZeroLen 36 case reflect.String: 37 return isZeroLen 38 case reflect.Bool: 39 return isZeroBool 40 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 41 return isZeroInt 42 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 43 return isZeroUint 44 case reflect.Float32, reflect.Float64: 45 return isZeroFloat 46 case reflect.Interface, reflect.Ptr, reflect.Slice, reflect.Map: 47 return isNil 48 } 49 50 if typ.Implements(driverValuerType) { 51 return isZeroDriverValue 52 } 53 54 return notZero 55 } 56 57 func addrChecker(fn IsZeroerFunc) IsZeroerFunc { 58 return func(v reflect.Value) bool { 59 if !v.CanAddr() { 60 return false 61 } 62 return fn(v.Addr()) 63 } 64 } 65 66 func isZeroInterface(v reflect.Value) bool { 67 if v.Kind() == reflect.Ptr && v.IsNil() { 68 return true 69 } 70 return v.Interface().(isZeroer).IsZero() 71 } 72 73 func isZeroDriverValue(v reflect.Value) bool { 74 if v.Kind() == reflect.Ptr { 75 return v.IsNil() 76 } 77 78 valuer := v.Interface().(driver.Valuer) 79 value, err := valuer.Value() 80 if err != nil { 81 return false 82 } 83 return value == nil 84 } 85 86 func isZeroLen(v reflect.Value) bool { 87 return v.Len() == 0 88 } 89 90 func isNil(v reflect.Value) bool { 91 return v.IsNil() 92 } 93 94 func isZeroBool(v reflect.Value) bool { 95 return !v.Bool() 96 } 97 98 func isZeroInt(v reflect.Value) bool { 99 return v.Int() == 0 100 } 101 102 func isZeroUint(v reflect.Value) bool { 103 return v.Uint() == 0 104 } 105 106 func isZeroFloat(v reflect.Value) bool { 107 return v.Float() == 0 108 } 109 110 func isZeroBytes(v reflect.Value) bool { 111 b := v.Slice(0, v.Len()).Bytes() 112 for _, c := range b { 113 if c != 0 { 114 return false 115 } 116 } 117 return true 118 } 119 120 func notZero(v reflect.Value) bool { 121 return false 122 }