isinit.go 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. // Copyright 2019 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style.
  3. // license that can be found in the LICENSE file.
  4. package proto
  5. import (
  6. "bytes"
  7. "fmt"
  8. "google.golang.org/protobuf/internal/errors"
  9. pref "google.golang.org/protobuf/reflect/protoreflect"
  10. )
  11. // IsInitialized returns an error if any required fields in m are not set.
  12. func IsInitialized(m Message) error {
  13. if methods := protoMethods(m); methods != nil && methods.IsInitialized != nil {
  14. if err := methods.IsInitialized(m); err == nil {
  15. return nil
  16. }
  17. // Fall through to the slow path, since the fast-path
  18. // implementation doesn't produce nice errors.
  19. //
  20. // TODO: Consider producing better errors from the fast path.
  21. }
  22. return isInitialized(m.ProtoReflect(), nil)
  23. }
  24. // IsInitialized returns an error if any required fields in m are not set.
  25. func isInitialized(m pref.Message, stack []interface{}) error {
  26. md := m.Descriptor()
  27. fds := md.Fields()
  28. for i, nums := 0, md.RequiredNumbers(); i < nums.Len(); i++ {
  29. fd := fds.ByNumber(nums.Get(i))
  30. if !m.Has(fd) {
  31. stack = append(stack, fd.Name())
  32. return newRequiredNotSetError(stack)
  33. }
  34. }
  35. var err error
  36. m.Range(func(fd pref.FieldDescriptor, v pref.Value) bool {
  37. // Recurse into fields containing message values.
  38. stack := append(stack, fd.Name())
  39. switch {
  40. case fd.IsList():
  41. if fd.Message() == nil {
  42. return true
  43. }
  44. for i, list := 0, v.List(); i < list.Len() && err == nil; i++ {
  45. stack := append(stack, "[", i, "].")
  46. err = isInitialized(list.Get(i).Message(), stack)
  47. }
  48. case fd.IsMap():
  49. if fd.MapValue().Message() == nil {
  50. return true
  51. }
  52. v.Map().Range(func(key pref.MapKey, v pref.Value) bool {
  53. stack := append(stack, "[", key, "].")
  54. err = isInitialized(v.Message(), stack)
  55. return err == nil
  56. })
  57. default:
  58. if fd.Message() == nil {
  59. return true
  60. }
  61. stack := append(stack, ".")
  62. err = isInitialized(v.Message(), stack)
  63. }
  64. return err == nil
  65. })
  66. return err
  67. }
  68. func newRequiredNotSetError(stack []interface{}) error {
  69. var buf bytes.Buffer
  70. for _, s := range stack {
  71. fmt.Fprint(&buf, s)
  72. }
  73. return errors.RequiredNotSet(buf.String())
  74. }