wrapperopaque.go 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. // Copyright 2024 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. // ValueOrNil returns nil if has is false, or a pointer to a new variable
  6. // containing the value returned by the specified getter.
  7. //
  8. // This function is similar to the wrappers (proto.Int32(), proto.String(),
  9. // etc.), but is generic (works for any field type) and works with the hasser
  10. // and getter of a field, as opposed to a value.
  11. //
  12. // This is convenient when populating builder fields.
  13. //
  14. // Example:
  15. //
  16. // hop := attr.GetDirectHop()
  17. // injectedRoute := ripb.InjectedRoute_builder{
  18. // Prefixes: route.GetPrefixes(),
  19. // NextHop: proto.ValueOrNil(hop.HasAddress(), hop.GetAddress),
  20. // }
  21. func ValueOrNil[T any](has bool, getter func() T) *T {
  22. if !has {
  23. return nil
  24. }
  25. v := getter()
  26. return &v
  27. }
  28. // ValueOrDefault returns the protobuf message val if val is not nil, otherwise
  29. // it returns a pointer to an empty val message.
  30. //
  31. // This function allows for translating code from the old Open Struct API to the
  32. // new Opaque API.
  33. //
  34. // The old Open Struct API represented oneof fields with a wrapper struct:
  35. //
  36. // var signedImg *accountpb.SignedImage
  37. // profile := &accountpb.Profile{
  38. // // The Avatar oneof will be set, with an empty SignedImage.
  39. // Avatar: &accountpb.Profile_SignedImage{signedImg},
  40. // }
  41. //
  42. // The new Opaque API treats oneof fields like regular fields, there are no more
  43. // wrapper structs:
  44. //
  45. // var signedImg *accountpb.SignedImage
  46. // profile := &accountpb.Profile{}
  47. // profile.SetSignedImage(signedImg)
  48. //
  49. // For convenience, the Opaque API also offers Builders, which allow for a
  50. // direct translation of struct initialization. However, because Builders use
  51. // nilness to represent field presence (but there is no non-nil wrapper struct
  52. // anymore), Builders cannot distinguish between an unset oneof and a set oneof
  53. // with nil message. The above code would need to be translated with help of the
  54. // ValueOrDefault function to retain the same behavior:
  55. //
  56. // var signedImg *accountpb.SignedImage
  57. // return &accountpb.Profile_builder{
  58. // SignedImage: proto.ValueOrDefault(signedImg),
  59. // }.Build()
  60. func ValueOrDefault[T interface {
  61. *P
  62. Message
  63. }, P any](val T) T {
  64. if val == nil {
  65. return T(new(P))
  66. }
  67. return val
  68. }
  69. // ValueOrDefaultBytes is like ValueOrDefault but for working with fields of
  70. // type []byte.
  71. func ValueOrDefaultBytes(val []byte) []byte {
  72. if val == nil {
  73. return []byte{}
  74. }
  75. return val
  76. }