Repository navigation
Expand file tree
/
Copy pathtypes.go
More file actions
81 lines (77 loc) · 3.92 KB
/
Copy pathtypes.go
File metadata and controls
81 lines (77 loc) · 3.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package validator
// FieldError is one recorded failure: a rule or filter that rejected a field.
// Errors resolves Message through the Validator's templates on every read;
// Errors.Items returns copies with the final text filled in.
type FieldError struct {
// Field is the validation name; dive elements are reported as "field[i]"
// for slices and arrays and "field[key]" for maps.
Field string
// Rule is the failing rule's signature, "!" for a negation, "||" for an
// alternation with no passing branch, or "" for a failed filter.
Rule string
// Message is the raw template with {field}, {0}, {1}, ... and {N+}
// placeholders; Errors resolves it, honoring overrides and translations.
Message string
// Params are the rule's arguments, substituted for {0}, {1}, ...; {N+}
// joins the arguments from N on with ", ".
Params []string
}
// Rule is a leaf boolean check; composition with &&, || and ! is the
// expression's job. A Validator is shared between goroutines, so
// implementations must be safe for concurrent use. Passes must be
// deterministic and side-effect free: the engine evaluates a rule more than
// once for one value (a fast probe before diagnostics on dive elements, Valid
// versus Validate), so a rule that answers differently on the second call
// produces inconsistent reports. The *Field is pooled and only valid during
// the call. A check that performs I/O or can fail implements FallibleRule
// instead.
//
// By convention empty values pass (IsEmpty), leaving presence to required,
// filled and notblank, so rules compose without repeating presence checks.
type Rule interface {
// Signature returns the name used in expressions: letters, digits and
// underscores, not starting with a digit, and not the reserved "dive".
Signature() string
// Passes reports whether the field's current value is acceptable. It
// must not retain f or the slice returned by f.Attrs after returning.
Passes(f *Field) bool
// Message returns the failure template; {field} is the display name and
// {0}, {1}, ... the arguments. An empty template renders as
// "The {field} is invalid.".
Message() string
}
// FallibleRule is a rule backed by an operation that can fail, such as a
// database lookup. The Rule contract applies (concurrency-safe, deterministic
// for one input, pooled Field not retained), and false with a nil error is an
// ordinary field failure. A non-nil error means the check could not be
// completed: it is returned as a *RuleError wrapping ErrRuleEvaluation, is
// never recorded as a field failure, and skips the rest of that field's
// expression while other fields still run. Use f.Context to bound the
// operation.
type FallibleRule interface {
// Signature returns the name used in expressions, under the same rules as
// Rule.Signature; one name cannot be registered as both kinds.
Signature() string
// Validate reports whether the value is acceptable, or an error when the
// check itself failed. It must not retain f after returning.
Validate(f *Field) (bool, error)
// Message returns the failure template used when Validate returns false
// with a nil error.
Message() string
}
// Filter transforms an input value before its rules see it and before
// ValidateAs binds it: trimming, case folding, type coercion. A field's chain
// ("trim|lower") runs once at Validate, in order, only on a present non-nil
// value, and never on a field with dive rules. A returned error, or a panic
// (recovered), is recorded as a field failure whose message is the error
// text; the raw value is never used silently. Implementations must be safe
// for concurrent use.
type Filter interface {
// Signature returns the name used in filter chains, under the same rules
// as Rule.Signature.
Signature() string
// Handle returns the transformed value; args are the chain arguments
// ("trim:xy" passes "xy"). A value that cannot be transformed should be
// an error rather than a silent zero.
Handle(val any, args ...string) (any, error)
}