validators.go 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. /*
  2. Copyright © The ESO Authors
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. https://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package esutils
  14. import (
  15. "errors"
  16. "fmt"
  17. )
  18. var (
  19. // ErrValueAndRefConflict is returned when both a value and reference are set.
  20. ErrValueAndRefConflict = errors.New("cannot specify both value and reference")
  21. // ErrValueOrRefMissing is returned when neither a value nor reference is set.
  22. ErrValueOrRefMissing = errors.New("must specify either value or reference")
  23. // ErrRefRequired is returned when a reference is required but missing.
  24. ErrRefRequired = errors.New("reference is required")
  25. // ErrValueNotAllowed is returned when a value is set but only a reference is allowed.
  26. ErrValueNotAllowed = errors.New("value must not be specified")
  27. // ErrValueRequired is returned when a value is required but missing.
  28. ErrValueRequired = errors.New("value is required")
  29. // ErrRefNotAllowed is returned when a reference is set but only a value is allowed.
  30. ErrRefNotAllowed = errors.New("reference must not be specified")
  31. )
  32. // RefPresencePolicy describes which side of a value/reference pair is allowed.
  33. type RefPresencePolicy int
  34. const (
  35. // RequireValueOrRef requires exactly one of value or reference to be set.
  36. RequireValueOrRef RefPresencePolicy = iota
  37. // AllowValueOrRef allows neither value nor reference to be set, but rejects both being set.
  38. AllowValueOrRef
  39. // RequireRefOnly requires reference to be set and value to be empty.
  40. RequireRefOnly
  41. // RequireValueOnly requires value to be set and reference to be empty.
  42. RequireValueOnly
  43. )
  44. // ValueOrRefPolicy configures ValidateValueOrRef.
  45. type ValueOrRefPolicy[T any] struct {
  46. Presence RefPresencePolicy
  47. ValidateRef func(T) error
  48. }
  49. // ValidateValueOrRef validates fields that allow a direct value or a reference.
  50. func ValidateValueOrRef[T any](value string, ref *T, policy ValueOrRefPolicy[T]) error {
  51. switch policy.Presence {
  52. case RequireValueOrRef:
  53. if value != "" && ref != nil {
  54. return ErrValueAndRefConflict
  55. }
  56. if value == "" && ref == nil {
  57. return ErrValueOrRefMissing
  58. }
  59. case AllowValueOrRef:
  60. if value != "" && ref != nil {
  61. return ErrValueAndRefConflict
  62. }
  63. case RequireRefOnly:
  64. if ref == nil {
  65. return ErrRefRequired
  66. }
  67. if value != "" {
  68. return ErrValueNotAllowed
  69. }
  70. case RequireValueOnly:
  71. if value == "" {
  72. return ErrValueRequired
  73. }
  74. if ref != nil {
  75. return ErrRefNotAllowed
  76. }
  77. default:
  78. return fmt.Errorf("unknown value/reference presence policy: %d", policy.Presence)
  79. }
  80. if ref != nil && policy.ValidateRef != nil {
  81. return policy.ValidateRef(*ref)
  82. }
  83. return nil
  84. }