github.com/aavshr/aws-sdk-go@v1.41.3/private/model/api/shape_validation.go (about) 1 //go:build codegen 2 // +build codegen 3 4 package api 5 6 import ( 7 "bytes" 8 "fmt" 9 "text/template" 10 ) 11 12 // A ShapeValidationType is the type of validation that a shape needs 13 type ShapeValidationType int 14 15 const ( 16 // ShapeValidationRequired states the shape must be set 17 ShapeValidationRequired = iota 18 19 // ShapeValidationMinVal states the shape must have at least a number of 20 // elements, or for numbers a minimum value 21 ShapeValidationMinVal 22 23 // ShapeValidationNested states the shape has nested values that need 24 // to be validated 25 ShapeValidationNested 26 ) 27 28 // A ShapeValidation contains information about a shape and the type of validation 29 // that is needed 30 type ShapeValidation struct { 31 // Name of the shape to be validated 32 Name string 33 // Reference to the shape within the context the shape is referenced 34 Ref *ShapeRef 35 // Type of validation needed 36 Type ShapeValidationType 37 } 38 39 var validationGoCodeTmpls = template.Must( 40 template.New("validationGoCodeTmpls"). 41 Funcs(template.FuncMap{ 42 "getMin": func(ref *ShapeRef) float64 { 43 if !ref.CanBeEmpty() && ref.Shape.Min <= 0 { 44 return 1 45 } 46 47 return ref.Shape.Min 48 }, 49 }). 50 Parse(` 51 {{ define "requiredValue" -}} 52 if s.{{ .Name }} == nil { 53 invalidParams.Add(request.NewErrParamRequired("{{ .Name }}")) 54 } 55 {{- end }} 56 {{ define "minLen" -}} 57 {{- $min := getMin .Ref -}} 58 if s.{{ .Name }} != nil && len(s.{{ .Name }}) < {{ $min }} { 59 invalidParams.Add(request.NewErrParamMinLen("{{ .Name }}", {{ $min }})) 60 } 61 {{- end }} 62 {{ define "minLenString" -}} 63 {{- $min := getMin .Ref -}} 64 if s.{{ .Name }} != nil && len(*s.{{ .Name }}) < {{ $min }} { 65 invalidParams.Add(request.NewErrParamMinLen("{{ .Name }}", {{ $min }})) 66 } 67 {{- end }} 68 {{ define "minVal" -}} 69 {{- $min := getMin .Ref -}} 70 if s.{{ .Name }} != nil && *s.{{ .Name }} < {{ $min }} { 71 invalidParams.Add(request.NewErrParamMinValue("{{ .Name }}", {{ $min }})) 72 } 73 {{- end }} 74 {{ define "nestedMapList" -}} 75 if s.{{ .Name }} != nil { 76 for i, v := range s.{{ .Name }} { 77 if v == nil { continue } 78 if err := v.Validate(); err != nil { 79 invalidParams.AddNested(fmt.Sprintf("%s[%v]", "{{ .Name }}", i), err.(request.ErrInvalidParams)) 80 } 81 } 82 } 83 {{- end }} 84 {{ define "nestedStruct" -}} 85 if s.{{ .Name }} != nil { 86 if err := s.{{ .Name }}.Validate(); err != nil { 87 invalidParams.AddNested("{{ .Name }}", err.(request.ErrInvalidParams)) 88 } 89 } 90 {{- end }} 91 `)) 92 93 // GoCode returns the generated Go code for the Shape with its validation type. 94 func (sv ShapeValidation) GoCode() string { 95 var err error 96 97 w := &bytes.Buffer{} 98 switch sv.Type { 99 case ShapeValidationRequired: 100 err = validationGoCodeTmpls.ExecuteTemplate(w, "requiredValue", sv) 101 case ShapeValidationMinVal: 102 switch sv.Ref.Shape.Type { 103 case "list", "map", "blob": 104 err = validationGoCodeTmpls.ExecuteTemplate(w, "minLen", sv) 105 case "string": 106 err = validationGoCodeTmpls.ExecuteTemplate(w, "minLenString", sv) 107 case "integer", "long", "float", "double": 108 err = validationGoCodeTmpls.ExecuteTemplate(w, "minVal", sv) 109 default: 110 panic(fmt.Sprintf("ShapeValidation.GoCode, %s's type %s, no min value handling", 111 sv.Name, sv.Ref.Shape.Type)) 112 } 113 case ShapeValidationNested: 114 switch sv.Ref.Shape.Type { 115 case "map", "list": 116 err = validationGoCodeTmpls.ExecuteTemplate(w, "nestedMapList", sv) 117 default: 118 err = validationGoCodeTmpls.ExecuteTemplate(w, "nestedStruct", sv) 119 } 120 default: 121 panic(fmt.Sprintf("ShapeValidation.GoCode, %s's type %d, unknown validation type", 122 sv.Name, sv.Type)) 123 } 124 125 if err != nil { 126 panic(fmt.Sprintf("ShapeValidation.GoCode failed, err: %v", err)) 127 } 128 129 return w.String() 130 } 131 132 // A ShapeValidations is a collection of shape validations needed nested within 133 // a parent shape 134 type ShapeValidations []ShapeValidation 135 136 var validateShapeTmpl = template.Must(template.New("ValidateShape").Parse(` 137 // Validate inspects the fields of the type to determine if they are valid. 138 func (s *{{ .Shape.ShapeName }}) Validate() error { 139 invalidParams := request.ErrInvalidParams{Context: "{{ .Shape.ShapeName }}"} 140 {{ range $_, $v := .Validations -}} 141 {{ $v.GoCode }} 142 {{ end }} 143 if invalidParams.Len() > 0 { 144 return invalidParams 145 } 146 return nil 147 } 148 `)) 149 150 // GoCode generates the Go code needed to perform validations for the 151 // shape and its nested fields. 152 func (vs ShapeValidations) GoCode(shape *Shape) string { 153 buf := &bytes.Buffer{} 154 validateShapeTmpl.Execute(buf, map[string]interface{}{ 155 "Shape": shape, 156 "Validations": vs, 157 }) 158 return buf.String() 159 } 160 161 // Has returns true or false if the ShapeValidations already contains the 162 // the reference and validation type. 163 func (vs ShapeValidations) Has(ref *ShapeRef, typ ShapeValidationType) bool { 164 for _, v := range vs { 165 if v.Ref == ref && v.Type == typ { 166 return true 167 } 168 } 169 return false 170 }