validation.go (3675B)
1 package smithy 2 3 import ( 4 "bytes" 5 "fmt" 6 "strings" 7 ) 8 9 // An InvalidParamsError provides wrapping of invalid parameter errors found when 10 // validating API operation input parameters. 11 type InvalidParamsError struct { 12 // Context is the base context of the invalid parameter group. 13 Context string 14 errs []InvalidParamError 15 } 16 17 // Add adds a new invalid parameter error to the collection of invalid 18 // parameters. The context of the invalid parameter will be updated to reflect 19 // this collection. 20 func (e *InvalidParamsError) Add(err InvalidParamError) { 21 err.SetContext(e.Context) 22 e.errs = append(e.errs, err) 23 } 24 25 // AddNested adds the invalid parameter errors from another InvalidParamsError 26 // value into this collection. The nested errors will have their nested context 27 // updated and base context to reflect the merging. 28 // 29 // Use for nested validations errors. 30 func (e *InvalidParamsError) AddNested(nestedCtx string, nested InvalidParamsError) { 31 for _, err := range nested.errs { 32 err.SetContext(e.Context) 33 err.AddNestedContext(nestedCtx) 34 e.errs = append(e.errs, err) 35 } 36 } 37 38 // Len returns the number of invalid parameter errors 39 func (e *InvalidParamsError) Len() int { 40 return len(e.errs) 41 } 42 43 // Error returns the string formatted form of the invalid parameters. 44 func (e InvalidParamsError) Error() string { 45 w := &bytes.Buffer{} 46 fmt.Fprintf(w, "%d validation error(s) found.\n", len(e.errs)) 47 48 for _, err := range e.errs { 49 fmt.Fprintf(w, "- %s\n", err.Error()) 50 } 51 52 return w.String() 53 } 54 55 // Errs returns a slice of the invalid parameters 56 func (e InvalidParamsError) Errs() []error { 57 errs := make([]error, len(e.errs)) 58 for i := 0; i < len(errs); i++ { 59 errs[i] = e.errs[i] 60 } 61 62 return errs 63 } 64 65 // An InvalidParamError represents an invalid parameter error type. 66 type InvalidParamError interface { 67 error 68 69 // Field name the error occurred on. 70 Field() string 71 72 // SetContext updates the context of the error. 73 SetContext(string) 74 75 // AddNestedContext updates the error's context to include a nested level. 76 AddNestedContext(string) 77 } 78 79 type invalidParamError struct { 80 context string 81 nestedContext string 82 field string 83 reason string 84 } 85 86 // Error returns the string version of the invalid parameter error. 87 func (e invalidParamError) Error() string { 88 return fmt.Sprintf("%s, %s.", e.reason, e.Field()) 89 } 90 91 // Field Returns the field and context the error occurred. 92 func (e invalidParamError) Field() string { 93 sb := &strings.Builder{} 94 sb.WriteString(e.context) 95 if sb.Len() > 0 { 96 if len(e.nestedContext) == 0 || (len(e.nestedContext) > 0 && e.nestedContext[:1] != "[") { 97 sb.WriteRune('.') 98 } 99 } 100 if len(e.nestedContext) > 0 { 101 sb.WriteString(e.nestedContext) 102 sb.WriteRune('.') 103 } 104 sb.WriteString(e.field) 105 return sb.String() 106 } 107 108 // SetContext updates the base context of the error. 109 func (e *invalidParamError) SetContext(ctx string) { 110 e.context = ctx 111 } 112 113 // AddNestedContext prepends a context to the field's path. 114 func (e *invalidParamError) AddNestedContext(ctx string) { 115 if len(e.nestedContext) == 0 { 116 e.nestedContext = ctx 117 return 118 } 119 // Check if our nested context is an index into a slice or map 120 if e.nestedContext[:1] != "[" { 121 e.nestedContext = fmt.Sprintf("%s.%s", ctx, e.nestedContext) 122 return 123 } 124 e.nestedContext = ctx + e.nestedContext 125 } 126 127 // An ParamRequiredError represents an required parameter error. 128 type ParamRequiredError struct { 129 invalidParamError 130 } 131 132 // NewErrParamRequired creates a new required parameter error. 133 func NewErrParamRequired(field string) *ParamRequiredError { 134 return &ParamRequiredError{ 135 invalidParamError{ 136 field: field, 137 reason: fmt.Sprintf("missing required field"), 138 }, 139 } 140 }