86 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			86 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			Go
		
	
	
	
| package validators
 | |
| 
 | |
| import (
 | |
| 	"reflect"
 | |
| 
 | |
| 	validation "github.com/go-ozzo/ozzo-validation/v4"
 | |
| )
 | |
| 
 | |
| // Equal checks whether the validated value matches another one from the same type.
 | |
| //
 | |
| // It expects the compared values to be from the same type and works
 | |
| // with booleans, numbers, strings and their pointer variants.
 | |
| //
 | |
| // If one of the value is pointer, the comparison is based on its
 | |
| // underlying value (when possible to determine).
 | |
| //
 | |
| // Note that empty/zero values are also compared (this differ from other validation.RuleFunc).
 | |
| //
 | |
| // Example:
 | |
| //
 | |
| //	validation.Field(&form.PasswordConfirm, validation.By(validators.Equal(form.Password)))
 | |
| func Equal[T comparable](valueToCompare T) validation.RuleFunc {
 | |
| 	return func(value any) error {
 | |
| 		if compareValues(value, valueToCompare) {
 | |
| 			return nil
 | |
| 		}
 | |
| 
 | |
| 		return validation.NewError("validation_values_mismatch", "Values don't match.")
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func compareValues(a, b any) bool {
 | |
| 	if a == b {
 | |
| 		return true
 | |
| 	}
 | |
| 
 | |
| 	if checkIsNil(a) && checkIsNil(b) {
 | |
| 		return true
 | |
| 	}
 | |
| 
 | |
| 	var result bool
 | |
| 
 | |
| 	defer func() {
 | |
| 		if err := recover(); err != nil {
 | |
| 			result = false
 | |
| 		}
 | |
| 	}()
 | |
| 
 | |
| 	reflectA := reflect.ValueOf(a)
 | |
| 	reflectB := reflect.ValueOf(b)
 | |
| 
 | |
| 	dereferencedA := dereference(reflectA)
 | |
| 	dereferencedB := dereference(reflectB)
 | |
| 	if dereferencedA.CanInterface() && dereferencedB.CanInterface() {
 | |
| 		result = dereferencedA.Interface() == dereferencedB.Interface()
 | |
| 	}
 | |
| 
 | |
| 	return result
 | |
| }
 | |
| 
 | |
| // note https://github.com/golang/go/issues/51649
 | |
| func checkIsNil(value any) bool {
 | |
| 	if value == nil {
 | |
| 		return true
 | |
| 	}
 | |
| 
 | |
| 	var result bool
 | |
| 
 | |
| 	defer func() {
 | |
| 		if err := recover(); err != nil {
 | |
| 			result = false
 | |
| 		}
 | |
| 	}()
 | |
| 
 | |
| 	result = reflect.ValueOf(value).IsNil()
 | |
| 
 | |
| 	return result
 | |
| }
 | |
| 
 | |
| func dereference(v reflect.Value) reflect.Value {
 | |
| 	for v.Kind() == reflect.Pointer {
 | |
| 		v = v.Elem()
 | |
| 	}
 | |
| 	return v
 | |
| }
 |