package validator import ( "fmt" "google.golang.org/protobuf/reflect/protoreflect" validate "git.ikuban.com/server/kubanapis/kuban/api/validate" ) // validateInt32 验证 int32 func (e *Engine) validateInt32( vctx *ValidationContext, fieldRules *validate.FieldRules, rules *validate.Int32Rules, value int32, fieldPath string, errors *ValidationErrors, ) error { if rules.Const != nil && value != *rules.Const { defaultMsg := fmt.Sprintf("字段 %s 必须等于 %d", fieldPath, *rules.Const) errors.Add(NewValidationError(fieldPath, ErrCodeInvalidValue, e.getErrorMessage(fieldRules, vctx, "const", defaultMsg))) } if rules.Lt != nil && value >= *rules.Lt { defaultMsg := fmt.Sprintf("字段 %s 必须小于 %d", fieldPath, *rules.Lt) errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange, e.getErrorMessage(fieldRules, vctx, "range", defaultMsg))) } if rules.Lte != nil && value > *rules.Lte { defaultMsg := fmt.Sprintf("字段 %s 必须小于等于 %d", fieldPath, *rules.Lte) errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange, e.getErrorMessage(fieldRules, vctx, "range", defaultMsg))) } if rules.Gt != nil && value <= *rules.Gt { defaultMsg := fmt.Sprintf("字段 %s 必须大于 %d", fieldPath, *rules.Gt) errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange, e.getErrorMessage(fieldRules, vctx, "range", defaultMsg))) } if rules.Gte != nil && value < *rules.Gte { defaultMsg := fmt.Sprintf("字段 %s 必须大于等于 %d", fieldPath, *rules.Gte) errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange, e.getErrorMessage(fieldRules, vctx, "range", defaultMsg))) } return e.validateInt32In(value, rules, fieldPath, errors, fieldRules, vctx) } func (e *Engine) validateInt32In(value int32, rules *validate.Int32Rules, fieldPath string, errors *ValidationErrors, fieldRules *validate.FieldRules, vctx *ValidationContext) error { if len(rules.In) > 0 { found := false for _, v := range rules.In { if value == v { found = true break } } if !found { defaultMsg := fmt.Sprintf("字段 %s 的值不在允许的列表中", fieldPath) errors.Add(NewValidationError(fieldPath, ErrCodeInvalidValue, e.getErrorMessage(fieldRules, vctx, "in", defaultMsg))) } } if len(rules.NotIn) > 0 { for _, v := range rules.NotIn { if value == v { defaultMsg := fmt.Sprintf("字段 %s 的值在禁止列表中", fieldPath) errors.Add(NewValidationError(fieldPath, ErrCodeInvalidValue, e.getErrorMessage(fieldRules, vctx, "not_in", defaultMsg))) break } } } return nil } // validateInt64 验证 int64 func (e *Engine) validateInt64( vctx *ValidationContext, fieldRules *validate.FieldRules, rules *validate.Int64Rules, value int64, fieldPath string, errors *ValidationErrors, ) error { if rules.Const != nil && value != *rules.Const { defaultMsg := fmt.Sprintf("字段 %s 必须等于 %d", fieldPath, *rules.Const) errors.Add(NewValidationError(fieldPath, ErrCodeInvalidValue, e.getErrorMessage(fieldRules, vctx, "const", defaultMsg))) } if rules.Lt != nil && value >= *rules.Lt { defaultMsg := fmt.Sprintf("字段 %s 必须小于 %d", fieldPath, *rules.Lt) errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange, e.getErrorMessage(fieldRules, vctx, "range", defaultMsg))) } if rules.Lte != nil && value > *rules.Lte { defaultMsg := fmt.Sprintf("字段 %s 必须小于等于 %d", fieldPath, *rules.Lte) errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange, e.getErrorMessage(fieldRules, vctx, "range", defaultMsg))) } if rules.Gt != nil && value <= *rules.Gt { defaultMsg := fmt.Sprintf("字段 %s 必须大于 %d", fieldPath, *rules.Gt) errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange, e.getErrorMessage(fieldRules, vctx, "range", defaultMsg))) } if rules.Gte != nil && value < *rules.Gte { defaultMsg := fmt.Sprintf("字段 %s 必须大于等于 %d", fieldPath, *rules.Gte) errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange, e.getErrorMessage(fieldRules, vctx, "range", defaultMsg))) } return e.validateInt64In(value, rules, fieldPath, errors, fieldRules, vctx) } func (e *Engine) validateInt64In(value int64, rules *validate.Int64Rules, fieldPath string, errors *ValidationErrors, fieldRules *validate.FieldRules, vctx *ValidationContext) error { if len(rules.In) > 0 { found := false for _, v := range rules.In { if value == v { found = true break } } if !found { defaultMsg := fmt.Sprintf("字段 %s 的值不在允许的列表中", fieldPath) errors.Add(NewValidationError(fieldPath, ErrCodeInvalidValue, e.getErrorMessage(fieldRules, vctx, "in", defaultMsg))) } } if len(rules.NotIn) > 0 { for _, v := range rules.NotIn { if value == v { defaultMsg := fmt.Sprintf("字段 %s 的值在禁止列表中", fieldPath) errors.Add(NewValidationError(fieldPath, ErrCodeInvalidValue, e.getErrorMessage(fieldRules, vctx, "not_in", defaultMsg))) break } } } return nil } // validateUInt32 验证 uint32 func (e *Engine) validateUInt32( vctx *ValidationContext, fieldRules *validate.FieldRules, rules *validate.UInt32Rules, value uint32, fieldPath string, errors *ValidationErrors, ) error { if rules.Const != nil && value != *rules.Const { defaultMsg := fmt.Sprintf("字段 %s 必须等于 %d", fieldPath, *rules.Const) errors.Add(NewValidationError(fieldPath, ErrCodeInvalidValue, e.getErrorMessage(fieldRules, vctx, "const", defaultMsg))) } if rules.Lt != nil && value >= *rules.Lt { defaultMsg := fmt.Sprintf("字段 %s 必须小于 %d", fieldPath, *rules.Lt) errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange, e.getErrorMessage(fieldRules, vctx, "range", defaultMsg))) } if rules.Lte != nil && value > *rules.Lte { defaultMsg := fmt.Sprintf("字段 %s 必须小于等于 %d", fieldPath, *rules.Lte) errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange, e.getErrorMessage(fieldRules, vctx, "range", defaultMsg))) } if rules.Gt != nil && value <= *rules.Gt { defaultMsg := fmt.Sprintf("字段 %s 必须大于 %d", fieldPath, *rules.Gt) errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange, e.getErrorMessage(fieldRules, vctx, "range", defaultMsg))) } if rules.Gte != nil && value < *rules.Gte { defaultMsg := fmt.Sprintf("字段 %s 必须大于等于 %d", fieldPath, *rules.Gte) errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange, e.getErrorMessage(fieldRules, vctx, "range", defaultMsg))) } return e.validateUInt32In(value, rules, fieldPath, errors, fieldRules, vctx) } func (e *Engine) validateUInt32In(value uint32, rules *validate.UInt32Rules, fieldPath string, errors *ValidationErrors, fieldRules *validate.FieldRules, vctx *ValidationContext) error { if len(rules.In) > 0 { found := false for _, v := range rules.In { if value == v { found = true break } } if !found { defaultMsg := fmt.Sprintf("字段 %s 的值不在允许的列表中", fieldPath) errors.Add(NewValidationError(fieldPath, ErrCodeInvalidValue, e.getErrorMessage(fieldRules, vctx, "in", defaultMsg))) } } if len(rules.NotIn) > 0 { for _, v := range rules.NotIn { if value == v { defaultMsg := fmt.Sprintf("字段 %s 的值在禁止列表中", fieldPath) errors.Add(NewValidationError(fieldPath, ErrCodeInvalidValue, e.getErrorMessage(fieldRules, vctx, "not_in", defaultMsg))) break } } } return nil } // validateUInt64 验证 uint64 func (e *Engine) validateUInt64( vctx *ValidationContext, fieldRules *validate.FieldRules, rules *validate.UInt64Rules, value uint64, fieldPath string, errors *ValidationErrors, ) error { if rules.Const != nil && value != *rules.Const { defaultMsg := fmt.Sprintf("字段 %s 必须等于 %d", fieldPath, *rules.Const) errors.Add(NewValidationError(fieldPath, ErrCodeInvalidValue, e.getErrorMessage(fieldRules, vctx, "const", defaultMsg))) } if rules.Lt != nil && value >= *rules.Lt { defaultMsg := fmt.Sprintf("字段 %s 必须小于 %d", fieldPath, *rules.Lt) errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange, e.getErrorMessage(fieldRules, vctx, "range", defaultMsg))) } if rules.Lte != nil && value > *rules.Lte { defaultMsg := fmt.Sprintf("字段 %s 必须小于等于 %d", fieldPath, *rules.Lte) errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange, e.getErrorMessage(fieldRules, vctx, "range", defaultMsg))) } if rules.Gt != nil && value <= *rules.Gt { defaultMsg := fmt.Sprintf("字段 %s 必须大于 %d", fieldPath, *rules.Gt) errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange, e.getErrorMessage(fieldRules, vctx, "range", defaultMsg))) } if rules.Gte != nil && value < *rules.Gte { defaultMsg := fmt.Sprintf("字段 %s 必须大于等于 %d", fieldPath, *rules.Gte) errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange, e.getErrorMessage(fieldRules, vctx, "range", defaultMsg))) } return e.validateUInt64In(value, rules, fieldPath, errors, fieldRules, vctx) } func (e *Engine) validateUInt64In(value uint64, rules *validate.UInt64Rules, fieldPath string, errors *ValidationErrors, fieldRules *validate.FieldRules, vctx *ValidationContext) error { if len(rules.In) > 0 { found := false for _, v := range rules.In { if value == v { found = true break } } if !found { defaultMsg := fmt.Sprintf("字段 %s 的值不在允许的列表中", fieldPath) errors.Add(NewValidationError(fieldPath, ErrCodeInvalidValue, e.getErrorMessage(fieldRules, vctx, "in", defaultMsg))) } } if len(rules.NotIn) > 0 { for _, v := range rules.NotIn { if value == v { defaultMsg := fmt.Sprintf("字段 %s 的值在禁止列表中", fieldPath) errors.Add(NewValidationError(fieldPath, ErrCodeInvalidValue, e.getErrorMessage(fieldRules, vctx, "not_in", defaultMsg))) break } } } return nil } // validateFloat 验证 float32 func (e *Engine) validateFloat( vctx *ValidationContext, fieldRules *validate.FieldRules, rules *validate.FloatRules, value float32, fieldPath string, errors *ValidationErrors, ) error { if rules.Const != nil && value != *rules.Const { defaultMsg := fmt.Sprintf("字段 %s 必须等于 %f", fieldPath, *rules.Const) errors.Add(NewValidationError(fieldPath, ErrCodeInvalidValue, e.getErrorMessage(fieldRules, vctx, "const", defaultMsg))) } if rules.Lt != nil && value >= *rules.Lt { defaultMsg := fmt.Sprintf("字段 %s 必须小于 %f", fieldPath, *rules.Lt) errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange, e.getErrorMessage(fieldRules, vctx, "range", defaultMsg))) } if rules.Lte != nil && value > *rules.Lte { defaultMsg := fmt.Sprintf("字段 %s 必须小于等于 %f", fieldPath, *rules.Lte) errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange, e.getErrorMessage(fieldRules, vctx, "range", defaultMsg))) } if rules.Gt != nil && value <= *rules.Gt { defaultMsg := fmt.Sprintf("字段 %s 必须大于 %f", fieldPath, *rules.Gt) errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange, e.getErrorMessage(fieldRules, vctx, "range", defaultMsg))) } if rules.Gte != nil && value < *rules.Gte { defaultMsg := fmt.Sprintf("字段 %s 必须大于等于 %f", fieldPath, *rules.Gte) errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange, e.getErrorMessage(fieldRules, vctx, "range", defaultMsg))) } return nil } // validateDouble 验证 float64 func (e *Engine) validateDouble( vctx *ValidationContext, fieldRules *validate.FieldRules, rules *validate.DoubleRules, value float64, fieldPath string, errors *ValidationErrors, ) error { if rules.Const != nil && value != *rules.Const { defaultMsg := fmt.Sprintf("字段 %s 必须等于 %f", fieldPath, *rules.Const) errors.Add(NewValidationError(fieldPath, ErrCodeInvalidValue, e.getErrorMessage(fieldRules, vctx, "const", defaultMsg))) } if rules.Lt != nil && value >= *rules.Lt { defaultMsg := fmt.Sprintf("字段 %s 必须小于 %f", fieldPath, *rules.Lt) errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange, e.getErrorMessage(fieldRules, vctx, "range", defaultMsg))) } if rules.Lte != nil && value > *rules.Lte { defaultMsg := fmt.Sprintf("字段 %s 必须小于等于 %f", fieldPath, *rules.Lte) errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange, e.getErrorMessage(fieldRules, vctx, "range", defaultMsg))) } if rules.Gt != nil && value <= *rules.Gt { defaultMsg := fmt.Sprintf("字段 %s 必须大于 %f", fieldPath, *rules.Gt) errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange, e.getErrorMessage(fieldRules, vctx, "range", defaultMsg))) } if rules.Gte != nil && value < *rules.Gte { defaultMsg := fmt.Sprintf("字段 %s 必须大于等于 %f", fieldPath, *rules.Gte) errors.Add(NewValidationError(fieldPath, ErrCodeOutOfRange, e.getErrorMessage(fieldRules, vctx, "range", defaultMsg))) } return nil } // validateBool 验证 bool func (e *Engine) validateBool( vctx *ValidationContext, fieldRules *validate.FieldRules, rules *validate.BoolRules, value bool, fieldPath string, errors *ValidationErrors, ) error { if rules.Const != nil && value != *rules.Const { defaultMsg := fmt.Sprintf("字段 %s 必须等于 %t", fieldPath, *rules.Const) errors.Add(NewValidationError(fieldPath, ErrCodeInvalidValue, e.getErrorMessage(fieldRules, vctx, "const", defaultMsg))) } return nil } // validateRepeated 验证 repeated 字段 func (e *Engine) validateRepeated( vctx *ValidationContext, fieldRules *validate.FieldRules, rules *validate.RepeatedRules, list protoreflect.List, field protoreflect.FieldDescriptor, fieldPath string, errors *ValidationErrors, ) error { if list == nil { return nil } size := list.Len() // 验证元素数量 if rules.MinItems != nil && uint64(size) < *rules.MinItems { defaultMsg := fmt.Sprintf("字段 %s 至少需要 %d 个元素", fieldPath, *rules.MinItems) errors.Add(NewValidationError(fieldPath, ErrCodeInvalidLength, e.getErrorMessage(fieldRules, vctx, "min_items", defaultMsg))) } if rules.MaxItems != nil && uint64(size) > *rules.MaxItems { defaultMsg := fmt.Sprintf("字段 %s 最多允许 %d 个元素", fieldPath, *rules.MaxItems) errors.Add(NewValidationError(fieldPath, ErrCodeInvalidLength, e.getErrorMessage(fieldRules, vctx, "max_items", defaultMsg))) } // 验证唯一性 if rules.Unique != nil && *rules.Unique { seen := make(map[interface{}]bool) for i := 0; i < size; i++ { item := list.Get(i).Interface() if seen[item] { defaultMsg := fmt.Sprintf("字段 %s 包含重复元素", fieldPath) errors.Add(NewValidationError(fieldPath, ErrCodeInvalidValue, e.getErrorMessage(fieldRules, vctx, "unique", defaultMsg))) break } seen[item] = true } } // TODO: 验证每个元素(需要递归调用validateFieldType) return nil } // validateMap 验证 map 字段 func (e *Engine) validateMap( vctx *ValidationContext, fieldRules *validate.FieldRules, rules *validate.MapRules, mapValue protoreflect.Map, field protoreflect.FieldDescriptor, fieldPath string, errors *ValidationErrors, ) error { if mapValue == nil { return nil } size := mapValue.Len() // 验证键值对数量 if rules.MinPairs != nil && uint64(size) < *rules.MinPairs { defaultMsg := fmt.Sprintf("字段 %s 至少需要 %d 个键值对", fieldPath, *rules.MinPairs) errors.Add(NewValidationError(fieldPath, ErrCodeInvalidLength, e.getErrorMessage(fieldRules, vctx, "min_pairs", defaultMsg))) } if rules.MaxPairs != nil && uint64(size) > *rules.MaxPairs { defaultMsg := fmt.Sprintf("字段 %s 最多允许 %d 个键值对", fieldPath, *rules.MaxPairs) errors.Add(NewValidationError(fieldPath, ErrCodeInvalidLength, e.getErrorMessage(fieldRules, vctx, "max_pairs", defaultMsg))) } // TODO: 验证 keys 和 values return nil }