msg.go 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. package goshared
  2. const msgTpl = `
  3. {{ if not (ignored .) -}}
  4. {{ if disabled . -}}
  5. {{ cmt "Validate is disabled for " (msgTyp .) ". This method will always return nil." }}
  6. {{- else -}}
  7. {{ cmt "Validate checks the field values on " (msgTyp .) " with the rules defined in the proto definition for this message. If any rules are violated, the first error encountered is returned, or nil if there are no violations." }}
  8. {{- end -}}
  9. func (m {{ (msgTyp .).Pointer }}) Validate() error {
  10. return m.validate(false)
  11. }
  12. {{ if disabled . -}}
  13. {{ cmt "ValidateAll is disabled for " (msgTyp .) ". This method will always return nil." }}
  14. {{- else -}}
  15. {{ cmt "ValidateAll checks the field values on " (msgTyp .) " with the rules defined in the proto definition for this message. If any rules are violated, the result is a list of violation errors wrapped in " (multierrname .) ", or nil if none found." }}
  16. {{- end -}}
  17. func (m {{ (msgTyp .).Pointer }}) ValidateAll() error {
  18. return m.validate(true)
  19. }
  20. {{/* Unexported function to handle validation. If the need arises to add more exported functions, please consider the functional option approach outlined in protoc-gen-validate#47. */}}
  21. func (m {{ (msgTyp .).Pointer }}) validate(all bool) error {
  22. {{ if disabled . -}}
  23. return nil
  24. {{ else -}}
  25. if m == nil { return nil }
  26. var errors []error
  27. {{ range .NonOneOfFields }}
  28. {{ render (context .) }}
  29. {{ end }}
  30. {{ range .OneOfs }}
  31. switch m.{{ name . }}.(type) {
  32. {{ range .Fields }}
  33. case {{ oneof . }}:
  34. {{ render (context .) }}
  35. {{ end }}
  36. {{ if required . }}
  37. default:
  38. err := {{ errname .Message }}{
  39. field: "{{ name . }}",
  40. reason: "value is required",
  41. }
  42. if !all { return err }
  43. errors = append(errors, err)
  44. {{ end }}
  45. }
  46. {{ end }}
  47. if len(errors) > 0 {
  48. return {{ multierrname . }}(errors)
  49. }
  50. return nil
  51. {{ end -}}
  52. }
  53. {{ if needs . "hostname" }}{{ template "hostname" . }}{{ end }}
  54. {{ if needs . "email" }}{{ template "email" . }}{{ end }}
  55. {{ if needs . "uuid" }}{{ template "uuid" . }}{{ end }}
  56. {{ cmt (multierrname .) " is an error wrapping multiple validation errors returned by " (msgTyp .) ".ValidateAll() if the designated constraints aren't met." -}}
  57. type {{ multierrname . }} []error
  58. // Error returns a concatenation of all the error messages it wraps.
  59. func (m {{ multierrname . }}) Error() string {
  60. var msgs []string
  61. for _, err := range m {
  62. msgs = append(msgs, err.Error())
  63. }
  64. return strings.Join(msgs, "; ")
  65. }
  66. // AllErrors returns a list of validation violation errors.
  67. func (m {{ multierrname . }}) AllErrors() []error { return m }
  68. {{ cmt (errname .) " is the validation error returned by " (msgTyp .) ".Validate if the designated constraints aren't met." -}}
  69. type {{ errname . }} struct {
  70. field string
  71. reason string
  72. cause error
  73. key bool
  74. }
  75. // Field function returns field value.
  76. func (e {{ errname . }}) Field() string { return e.field }
  77. // Reason function returns reason value.
  78. func (e {{ errname . }}) Reason() string { return e.reason }
  79. // Cause function returns cause value.
  80. func (e {{ errname . }}) Cause() error { return e.cause }
  81. // Key function returns key value.
  82. func (e {{ errname . }}) Key() bool { return e.key }
  83. // ErrorName returns error name.
  84. func (e {{ errname . }}) ErrorName() string { return "{{ errname . }}" }
  85. // Error satisfies the builtin error interface
  86. func (e {{ errname . }}) Error() string {
  87. cause := ""
  88. if e.cause != nil {
  89. cause = fmt.Sprintf(" | caused by: %v", e.cause)
  90. }
  91. key := ""
  92. if e.key {
  93. key = "key for "
  94. }
  95. return fmt.Sprintf(
  96. "invalid %s{{ (msgTyp .) }}.%s: %s%s",
  97. key,
  98. e.field,
  99. e.reason,
  100. cause)
  101. }
  102. var _ error = {{ errname . }}{}
  103. var _ interface{
  104. Field() string
  105. Reason() string
  106. Key() bool
  107. Cause() error
  108. ErrorName() string
  109. } = {{ errname . }}{}
  110. {{ range .Fields }}{{ with (context .) }}{{ $f := .Field }}
  111. {{ if has .Rules "In" }}{{ if .Rules.In }}
  112. var {{ lookup .Field "InLookup" }} = map[{{ inType .Field .Rules.In }}]struct{}{
  113. {{- range .Rules.In }}
  114. {{ inKey $f . }}: {},
  115. {{- end }}
  116. }
  117. {{ end }}{{ end }}
  118. {{ if has .Rules "NotIn" }}{{ if .Rules.NotIn }}
  119. var {{ lookup .Field "NotInLookup" }} = map[{{ inType .Field .Rules.In }}]struct{}{
  120. {{- range .Rules.NotIn }}
  121. {{ inKey $f . }}: {},
  122. {{- end }}
  123. }
  124. {{ end }}{{ end }}
  125. {{ if has .Rules "Pattern"}}{{ if .Rules.Pattern }}
  126. var {{ lookup .Field "Pattern" }} = regexp.MustCompile({{ lit .Rules.GetPattern }})
  127. {{ end }}{{ end }}
  128. {{ if has .Rules "Items"}}{{ if .Rules.Items }}
  129. {{ if has .Rules.Items.GetString_ "Pattern" }} {{ if .Rules.Items.GetString_.Pattern }}
  130. var {{ lookup .Field "Pattern" }} = regexp.MustCompile({{ lit .Rules.Items.GetString_.GetPattern }})
  131. {{ end }}{{ end }}
  132. {{ end }}{{ end }}
  133. {{ if has .Rules "Items"}}{{ if .Rules.Items }}
  134. {{ if has .Rules.Items.GetString_ "In" }} {{ if .Rules.Items.GetString_.In }}
  135. var {{ lookup .Field "InLookup" }} = map[string]struct{}{
  136. {{- range .Rules.Items.GetString_.In }}
  137. {{ inKey $f . }}: {},
  138. {{- end }}
  139. }
  140. {{ end }}{{ end }}
  141. {{ if has .Rules.Items.GetEnum "In" }} {{ if .Rules.Items.GetEnum.In }}
  142. var {{ lookup .Field "InLookup" }} = map[{{ inType .Field .Rules.Items.GetEnum.In }}]struct{}{
  143. {{- range .Rules.Items.GetEnum.In }}
  144. {{ inKey $f . }}: {},
  145. {{- end }}
  146. }
  147. {{ end }}{{ end }}
  148. {{ end }}{{ end }}
  149. {{ if has .Rules "Items"}}{{ if .Rules.Items }}
  150. {{ if has .Rules.Items.GetString_ "NotIn" }} {{ if .Rules.Items.GetString_.NotIn }}
  151. var {{ lookup .Field "NotInLookup" }} = map[string]struct{}{
  152. {{- range .Rules.Items.GetString_.NotIn }}
  153. {{ inKey $f . }}: {},
  154. {{- end }}
  155. }
  156. {{ end }}{{ end }}
  157. {{ if has .Rules.Items.GetEnum "NotIn" }} {{ if .Rules.Items.GetEnum.NotIn }}
  158. var {{ lookup .Field "NotInLookup" }} = map[{{ inType .Field .Rules.Items.GetEnum.NotIn }}]struct{}{
  159. {{- range .Rules.Items.GetEnum.NotIn }}
  160. {{ inKey $f . }}: {},
  161. {{- end }}
  162. }
  163. {{ end }}{{ end }}
  164. {{ end }}{{ end }}
  165. {{ if has .Rules "Keys"}}{{ if .Rules.Keys }}
  166. {{ if has .Rules.Keys.GetString_ "Pattern" }} {{ if .Rules.Keys.GetString_.Pattern }}
  167. var {{ lookup .Field "Pattern" }} = regexp.MustCompile({{ lit .Rules.Keys.GetString_.GetPattern }})
  168. {{ end }}{{ end }}
  169. {{ end }}{{ end }}
  170. {{ if has .Rules "Values"}}{{ if .Rules.Values }}
  171. {{ if has .Rules.Values.GetString_ "Pattern" }} {{ if .Rules.Values.GetString_.Pattern }}
  172. var {{ lookup .Field "Pattern" }} = regexp.MustCompile({{ lit .Rules.Values.GetString_.GetPattern }})
  173. {{ end }}{{ end }}
  174. {{ end }}{{ end }}
  175. {{ end }}{{ end }}
  176. {{- end -}}
  177. `