podman

Форк
0
175 строк · 5.3 Кб
1
package validator
2

3
import (
4
	"context"
5
	"reflect"
6
)
7

8
// StructLevelFunc accepts all values needed for struct level validation
9
type StructLevelFunc func(sl StructLevel)
10

11
// StructLevelFuncCtx accepts all values needed for struct level validation
12
// but also allows passing of contextual validation information via context.Context.
13
type StructLevelFuncCtx func(ctx context.Context, sl StructLevel)
14

15
// wrapStructLevelFunc wraps normal StructLevelFunc makes it compatible with StructLevelFuncCtx
16
func wrapStructLevelFunc(fn StructLevelFunc) StructLevelFuncCtx {
17
	return func(ctx context.Context, sl StructLevel) {
18
		fn(sl)
19
	}
20
}
21

22
// StructLevel contains all the information and helper functions
23
// to validate a struct
24
type StructLevel interface {
25

26
	// Validator returns the main validation object, in case one wants to call validations internally.
27
	// this is so you don't have to use anonymous functions to get access to the validate
28
	// instance.
29
	Validator() *Validate
30

31
	// Top returns the top level struct, if any
32
	Top() reflect.Value
33

34
	// Parent returns the current fields parent struct, if any
35
	Parent() reflect.Value
36

37
	// Current returns the current struct.
38
	Current() reflect.Value
39

40
	// ExtractType gets the actual underlying type of field value.
41
	// It will dive into pointers, customTypes and return you the
42
	// underlying value and its kind.
43
	ExtractType(field reflect.Value) (value reflect.Value, kind reflect.Kind, nullable bool)
44

45
	// ReportError reports an error just by passing the field and tag information
46
	//
47
	// NOTES:
48
	//
49
	// fieldName and altName get appended to the existing namespace that
50
	// validator is on. e.g. pass 'FirstName' or 'Names[0]' depending
51
	// on the nesting
52
	//
53
	// tag can be an existing validation tag or just something you make up
54
	// and process on the flip side it's up to you.
55
	ReportError(field interface{}, fieldName, structFieldName string, tag, param string)
56

57
	// ReportValidationErrors reports an error just by passing ValidationErrors
58
	//
59
	// NOTES:
60
	//
61
	// relativeNamespace and relativeActualNamespace get appended to the
62
	// existing namespace that validator is on.
63
	// e.g. pass 'User.FirstName' or 'Users[0].FirstName' depending
64
	// on the nesting. most of the time they will be blank, unless you validate
65
	// at a level lower the current field depth
66
	ReportValidationErrors(relativeNamespace, relativeActualNamespace string, errs ValidationErrors)
67
}
68

69
var _ StructLevel = new(validate)
70

71
// Top returns the top level struct
72
//
73
// NOTE: this can be the same as the current struct being validated
74
// if not is a nested struct.
75
//
76
// this is only called when within Struct and Field Level validation and
77
// should not be relied upon for an accurate value otherwise.
78
func (v *validate) Top() reflect.Value {
79
	return v.top
80
}
81

82
// Parent returns the current structs parent
83
//
84
// NOTE: this can be the same as the current struct being validated
85
// if not is a nested struct.
86
//
87
// this is only called when within Struct and Field Level validation and
88
// should not be relied upon for an accurate value otherwise.
89
func (v *validate) Parent() reflect.Value {
90
	return v.slflParent
91
}
92

93
// Current returns the current struct.
94
func (v *validate) Current() reflect.Value {
95
	return v.slCurrent
96
}
97

98
// Validator returns the main validation object, in case one want to call validations internally.
99
func (v *validate) Validator() *Validate {
100
	return v.v
101
}
102

103
// ExtractType gets the actual underlying type of field value.
104
func (v *validate) ExtractType(field reflect.Value) (reflect.Value, reflect.Kind, bool) {
105
	return v.extractTypeInternal(field, false)
106
}
107

108
// ReportError reports an error just by passing the field and tag information
109
func (v *validate) ReportError(field interface{}, fieldName, structFieldName, tag, param string) {
110

111
	fv, kind, _ := v.extractTypeInternal(reflect.ValueOf(field), false)
112

113
	if len(structFieldName) == 0 {
114
		structFieldName = fieldName
115
	}
116

117
	v.str1 = string(append(v.ns, fieldName...))
118

119
	if v.v.hasTagNameFunc || fieldName != structFieldName {
120
		v.str2 = string(append(v.actualNs, structFieldName...))
121
	} else {
122
		v.str2 = v.str1
123
	}
124

125
	if kind == reflect.Invalid {
126

127
		v.errs = append(v.errs,
128
			&fieldError{
129
				v:              v.v,
130
				tag:            tag,
131
				actualTag:      tag,
132
				ns:             v.str1,
133
				structNs:       v.str2,
134
				fieldLen:       uint8(len(fieldName)),
135
				structfieldLen: uint8(len(structFieldName)),
136
				param:          param,
137
				kind:           kind,
138
			},
139
		)
140
		return
141
	}
142

143
	v.errs = append(v.errs,
144
		&fieldError{
145
			v:              v.v,
146
			tag:            tag,
147
			actualTag:      tag,
148
			ns:             v.str1,
149
			structNs:       v.str2,
150
			fieldLen:       uint8(len(fieldName)),
151
			structfieldLen: uint8(len(structFieldName)),
152
			value:          fv.Interface(),
153
			param:          param,
154
			kind:           kind,
155
			typ:            fv.Type(),
156
		},
157
	)
158
}
159

160
// ReportValidationErrors reports ValidationErrors obtained from running validations within the Struct Level validation.
161
//
162
// NOTE: this function prepends the current namespace to the relative ones.
163
func (v *validate) ReportValidationErrors(relativeNamespace, relativeStructNamespace string, errs ValidationErrors) {
164

165
	var err *fieldError
166

167
	for i := 0; i < len(errs); i++ {
168

169
		err = errs[i].(*fieldError)
170
		err.ns = string(append(append(v.ns, relativeNamespace...), err.ns...))
171
		err.structNs = string(append(append(v.actualNs, relativeStructNamespace...), err.structNs...))
172

173
		v.errs = append(v.errs, err)
174
	}
175
}
176

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.