validation.go 3.6 KB

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