You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

checkinit.go 1.8 kB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  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. "google.golang.org/protobuf/internal/errors"
  7. "google.golang.org/protobuf/reflect/protoreflect"
  8. "google.golang.org/protobuf/runtime/protoiface"
  9. )
  10. // CheckInitialized returns an error if any required fields in m are not set.
  11. func CheckInitialized(m Message) error {
  12. return checkInitialized(m.ProtoReflect())
  13. }
  14. // CheckInitialized returns an error if any required fields in m are not set.
  15. func checkInitialized(m protoreflect.Message) error {
  16. if methods := protoMethods(m); methods != nil && methods.CheckInitialized != nil {
  17. _, err := methods.CheckInitialized(protoiface.CheckInitializedInput{
  18. Message: m,
  19. })
  20. return err
  21. }
  22. return checkInitializedSlow(m)
  23. }
  24. func checkInitializedSlow(m protoreflect.Message) error {
  25. md := m.Descriptor()
  26. fds := md.Fields()
  27. for i, nums := 0, md.RequiredNumbers(); i < nums.Len(); i++ {
  28. fd := fds.ByNumber(nums.Get(i))
  29. if !m.Has(fd) {
  30. return errors.RequiredNotSet(string(fd.FullName()))
  31. }
  32. }
  33. var err error
  34. m.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
  35. switch {
  36. case fd.IsList():
  37. if fd.Message() == nil {
  38. return true
  39. }
  40. for i, list := 0, v.List(); i < list.Len() && err == nil; i++ {
  41. err = checkInitialized(list.Get(i).Message())
  42. }
  43. case fd.IsMap():
  44. if fd.MapValue().Message() == nil {
  45. return true
  46. }
  47. v.Map().Range(func(key protoreflect.MapKey, v protoreflect.Value) bool {
  48. err = checkInitialized(v.Message())
  49. return err == nil
  50. })
  51. default:
  52. if fd.Message() == nil {
  53. return true
  54. }
  55. err = checkInitialized(v.Message())
  56. }
  57. return err == nil
  58. })
  59. return err
  60. }