-
Notifications
You must be signed in to change notification settings - Fork 40
Expand file tree
/
Copy pathpreprocess.go
More file actions
96 lines (86 loc) · 2.4 KB
/
Copy pathpreprocess.go
File metadata and controls
96 lines (86 loc) · 2.4 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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package zog
import (
"fmt"
"github.com/Oudwins/zog/conf"
p "github.com/Oudwins/zog/pkgs/internals"
"github.com/Oudwins/zog/zconst"
)
type PreprocessSchema[F any, T any] struct {
schema ZogSchema
fn func(data F, ctx Ctx) (out T, err error)
}
// out should never be a pointer type
func Preprocess[F any, T any](fn func(data F, ctx Ctx) (out T, err error), schema ZogSchema) *PreprocessSchema[F, T] {
return &PreprocessSchema[F, T]{fn: fn, schema: schema}
}
func (s *PreprocessSchema[F, T]) process(ctx *p.SchemaCtx) {
v, ok := ctx.Data.(F)
if !ok {
ctx.AddIssue(ctx.IssueFromCoerce(fmt.Errorf("preprocess expected %T but got %T", v, ctx.Data)))
return
}
out, err := s.fn(v, ctx)
if err != nil {
ctx.AddIssue(ctx.IssueFromUnknownError(err))
return
}
ctx.Data = p.UnwrapPtr(out)
s.schema.process(ctx)
}
func (s *PreprocessSchema[F, T]) validate(ctx *p.SchemaCtx) {
v, ok := ctx.ValPtr.(F)
if !ok {
ctx.AddIssue(ctx.IssueFromInvalidType("preprocess input type", ctx.ValPtr, "validating a preprocessed schema"))
return
}
out, err := s.fn(v, ctx)
if err != nil {
ctx.AddIssue(ctx.Issue().SetMessage(err.Error()))
return
}
switch v := ctx.ValPtr.(type) {
case *T:
*v = out
case **T:
*v = &out
default:
panic(fmt.Sprintf("Preprocessed should be passed in schema.Validate() a value pointer that is compatible with its returned type T. Either *T or **T. Got %T", v))
}
s.schema.validate(ctx)
}
func (s *PreprocessSchema[F, T]) getType() zconst.ZogType {
return s.schema.getType()
}
func (s *PreprocessSchema[F, T]) setCoercer(coercer CoercerFunc) {
s.schema.setCoercer(coercer)
}
func (s *PreprocessSchema[F, T]) Parse(data F, destPtr *T, options ...ExecOption) ZogIssueList {
errs := p.NewErrsList()
defer errs.Free()
ctx := p.NewExecCtx(errs, conf.IssueFormatter)
defer ctx.Free()
for _, opt := range options {
opt(ctx)
}
path := p.NewPathBuilder()
defer path.Free()
sctx := ctx.NewSchemaCtx(data, destPtr, path, s.getType())
defer sctx.Free()
s.process(sctx)
return errs.List
}
func (s *PreprocessSchema[F, T]) Validate(data *T, options ...ExecOption) ZogIssueList {
errs := p.NewErrsList()
defer errs.Free()
ctx := p.NewExecCtx(errs, conf.IssueFormatter)
defer ctx.Free()
for _, opt := range options {
opt(ctx)
}
path := p.NewPathBuilder()
defer path.Free()
sctx := ctx.NewSchemaCtx(data, data, path, s.getType())
defer sctx.Free()
s.validate(sctx)
return errs.List
}