mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-31 06:32:26 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			161 lines
		
	
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			161 lines
		
	
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package schema
 | |
| 
 | |
| import (
 | |
| 	"database/sql/driver"
 | |
| 	"reflect"
 | |
| )
 | |
| 
 | |
| var isZeroerType = reflect.TypeFor[isZeroer]()
 | |
| 
 | |
| type isZeroer interface {
 | |
| 	IsZero() bool
 | |
| }
 | |
| 
 | |
| func isZero(v interface{}) bool {
 | |
| 	switch v := v.(type) {
 | |
| 	case isZeroer:
 | |
| 		return v.IsZero()
 | |
| 	case string:
 | |
| 		return v == ""
 | |
| 	case []byte:
 | |
| 		return v == nil
 | |
| 	case int:
 | |
| 		return v == 0
 | |
| 	case int64:
 | |
| 		return v == 0
 | |
| 	case uint:
 | |
| 		return v == 0
 | |
| 	case uint64:
 | |
| 		return v == 0
 | |
| 	case float32:
 | |
| 		return v == 0
 | |
| 	case float64:
 | |
| 		return v == 0
 | |
| 	case int8:
 | |
| 		return v == 0
 | |
| 	case int16:
 | |
| 		return v == 0
 | |
| 	case int32:
 | |
| 		return v == 0
 | |
| 	case uint8:
 | |
| 		return v == 0
 | |
| 	case uint16:
 | |
| 		return v == 0
 | |
| 	case uint32:
 | |
| 		return v == 0
 | |
| 	default:
 | |
| 		rv := reflect.ValueOf(v)
 | |
| 		fn := zeroChecker(rv.Type())
 | |
| 		return fn(rv)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| type IsZeroerFunc func(reflect.Value) bool
 | |
| 
 | |
| func zeroChecker(typ reflect.Type) IsZeroerFunc {
 | |
| 	if typ.Implements(isZeroerType) {
 | |
| 		return isZeroInterface
 | |
| 	}
 | |
| 
 | |
| 	kind := typ.Kind()
 | |
| 
 | |
| 	if kind != reflect.Ptr {
 | |
| 		ptr := reflect.PointerTo(typ)
 | |
| 		if ptr.Implements(isZeroerType) {
 | |
| 			return addrChecker(isZeroInterface)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	switch kind {
 | |
| 	case reflect.Array:
 | |
| 		if typ.Elem().Kind() == reflect.Uint8 {
 | |
| 			return isZeroBytes
 | |
| 		}
 | |
| 		return isZeroLen
 | |
| 	case reflect.String:
 | |
| 		return isZeroLen
 | |
| 	case reflect.Bool:
 | |
| 		return isZeroBool
 | |
| 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
 | |
| 		return isZeroInt
 | |
| 	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
 | |
| 		return isZeroUint
 | |
| 	case reflect.Float32, reflect.Float64:
 | |
| 		return isZeroFloat
 | |
| 	case reflect.Interface, reflect.Ptr, reflect.Slice, reflect.Map:
 | |
| 		return isNil
 | |
| 	}
 | |
| 
 | |
| 	if typ.Implements(driverValuerType) {
 | |
| 		return isZeroDriverValue
 | |
| 	}
 | |
| 
 | |
| 	return notZero
 | |
| }
 | |
| 
 | |
| func addrChecker(fn IsZeroerFunc) IsZeroerFunc {
 | |
| 	return func(v reflect.Value) bool {
 | |
| 		if !v.CanAddr() {
 | |
| 			return false
 | |
| 		}
 | |
| 		return fn(v.Addr())
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func isZeroInterface(v reflect.Value) bool {
 | |
| 	if v.Kind() == reflect.Ptr && v.IsNil() {
 | |
| 		return true
 | |
| 	}
 | |
| 	return v.Interface().(isZeroer).IsZero()
 | |
| }
 | |
| 
 | |
| func isZeroDriverValue(v reflect.Value) bool {
 | |
| 	if v.Kind() == reflect.Ptr {
 | |
| 		return v.IsNil()
 | |
| 	}
 | |
| 
 | |
| 	valuer := v.Interface().(driver.Valuer)
 | |
| 	value, err := valuer.Value()
 | |
| 	if err != nil {
 | |
| 		return false
 | |
| 	}
 | |
| 	return value == nil
 | |
| }
 | |
| 
 | |
| func isZeroLen(v reflect.Value) bool {
 | |
| 	return v.Len() == 0
 | |
| }
 | |
| 
 | |
| func isNil(v reflect.Value) bool {
 | |
| 	return v.IsNil()
 | |
| }
 | |
| 
 | |
| func isZeroBool(v reflect.Value) bool {
 | |
| 	return !v.Bool()
 | |
| }
 | |
| 
 | |
| func isZeroInt(v reflect.Value) bool {
 | |
| 	return v.Int() == 0
 | |
| }
 | |
| 
 | |
| func isZeroUint(v reflect.Value) bool {
 | |
| 	return v.Uint() == 0
 | |
| }
 | |
| 
 | |
| func isZeroFloat(v reflect.Value) bool {
 | |
| 	return v.Float() == 0
 | |
| }
 | |
| 
 | |
| func isZeroBytes(v reflect.Value) bool {
 | |
| 	b := v.Slice(0, v.Len()).Bytes()
 | |
| 	for _, c := range b {
 | |
| 		if c != 0 {
 | |
| 			return false
 | |
| 		}
 | |
| 	}
 | |
| 	return true
 | |
| }
 | |
| 
 | |
| func notZero(v reflect.Value) bool {
 | |
| 	return false
 | |
| }
 |