message_field.go 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. // Copyright 2018 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 impl
  5. import (
  6. "fmt"
  7. "reflect"
  8. "github.com/golang/protobuf/v2/internal/flags"
  9. pref "github.com/golang/protobuf/v2/reflect/protoreflect"
  10. )
  11. type fieldInfo struct {
  12. // TODO: specialize marshal and unmarshal functions?
  13. has func(pointer) bool
  14. get func(pointer) pref.Value
  15. set func(pointer, pref.Value)
  16. clear func(pointer)
  17. mutable func(pointer) pref.Mutable
  18. }
  19. func fieldInfoForWeak(fd pref.FieldDescriptor, fs reflect.StructField) fieldInfo {
  20. if !flags.Proto1Legacy {
  21. panic("weak fields not supported")
  22. }
  23. // TODO: support weak fields.
  24. panic(fmt.Sprintf("invalid field: %v", fd))
  25. }
  26. func fieldInfoForOneof(fd pref.FieldDescriptor, fs reflect.StructField, ot reflect.Type) fieldInfo {
  27. // TODO: support oneof fields.
  28. panic(fmt.Sprintf("invalid field: %v", fd))
  29. }
  30. func fieldInfoForMap(fd pref.FieldDescriptor, fs reflect.StructField) fieldInfo {
  31. // TODO: support map fields.
  32. panic(fmt.Sprintf("invalid field: %v", fd))
  33. }
  34. func fieldInfoForVector(fd pref.FieldDescriptor, fs reflect.StructField) fieldInfo {
  35. // TODO: support vector fields.
  36. panic(fmt.Sprintf("invalid field: %v", fd))
  37. }
  38. var emptyBytes = reflect.ValueOf([]byte{})
  39. func fieldInfoForScalar(fd pref.FieldDescriptor, fs reflect.StructField) fieldInfo {
  40. ft := fs.Type
  41. nullable := fd.Syntax() == pref.Proto2
  42. if nullable {
  43. if ft.Kind() != reflect.Ptr && ft.Kind() != reflect.Slice {
  44. panic(fmt.Sprintf("invalid type: got %v, want pointer", ft))
  45. }
  46. if ft.Kind() == reflect.Ptr {
  47. ft = ft.Elem()
  48. }
  49. }
  50. conv := matchGoTypePBKind(ft, fd.Kind())
  51. fieldOffset := offsetOf(fs)
  52. // TODO: Implement unsafe fast path?
  53. return fieldInfo{
  54. has: func(p pointer) bool {
  55. rv := p.apply(fieldOffset).asType(fs.Type).Elem()
  56. if nullable {
  57. return !rv.IsNil()
  58. }
  59. switch rv.Kind() {
  60. case reflect.Bool:
  61. return rv.Bool()
  62. case reflect.Int32, reflect.Int64:
  63. return rv.Int() > 0
  64. case reflect.Uint32, reflect.Uint64:
  65. return rv.Uint() > 0
  66. case reflect.Float32, reflect.Float64:
  67. return rv.Float() > 0
  68. case reflect.String, reflect.Slice:
  69. return rv.Len() > 0
  70. default:
  71. panic(fmt.Sprintf("invalid type: %v", rv.Type())) // should never happen
  72. }
  73. },
  74. get: func(p pointer) pref.Value {
  75. rv := p.apply(fieldOffset).asType(fs.Type).Elem()
  76. if nullable {
  77. if rv.IsNil() {
  78. pv := fd.Default()
  79. if fd.Kind() == pref.BytesKind && len(pv.Bytes()) > 0 {
  80. return pref.ValueOf(append([]byte(nil), pv.Bytes()...)) // copy default bytes for safety
  81. }
  82. return pv
  83. }
  84. if rv.Kind() == reflect.Ptr {
  85. rv = rv.Elem()
  86. }
  87. }
  88. return conv.toPB(rv)
  89. },
  90. set: func(p pointer, v pref.Value) {
  91. rv := p.apply(fieldOffset).asType(fs.Type).Elem()
  92. if nullable && rv.Kind() == reflect.Ptr {
  93. if rv.IsNil() {
  94. rv.Set(reflect.New(ft))
  95. }
  96. rv = rv.Elem()
  97. }
  98. rv.Set(conv.toGo(v))
  99. if nullable && rv.Kind() == reflect.Slice && rv.IsNil() {
  100. rv.Set(emptyBytes)
  101. }
  102. },
  103. clear: func(p pointer) {
  104. rv := p.apply(fieldOffset).asType(fs.Type).Elem()
  105. rv.Set(reflect.Zero(rv.Type()))
  106. },
  107. mutable: func(p pointer) pref.Mutable {
  108. panic("invalid mutable call")
  109. },
  110. }
  111. }
  112. func fieldInfoForMessage(fd pref.FieldDescriptor, fs reflect.StructField) fieldInfo {
  113. // TODO: support vector fields.
  114. panic(fmt.Sprintf("invalid field: %v", fd))
  115. }
  116. // messageV1 is the protoV1.Message interface.
  117. type messageV1 interface {
  118. Reset()
  119. String() string
  120. ProtoMessage()
  121. }
  122. var (
  123. boolType = reflect.TypeOf(bool(false))
  124. int32Type = reflect.TypeOf(int32(0))
  125. int64Type = reflect.TypeOf(int64(0))
  126. uint32Type = reflect.TypeOf(uint32(0))
  127. uint64Type = reflect.TypeOf(uint64(0))
  128. float32Type = reflect.TypeOf(float32(0))
  129. float64Type = reflect.TypeOf(float64(0))
  130. stringType = reflect.TypeOf(string(""))
  131. bytesType = reflect.TypeOf([]byte(nil))
  132. enumIfaceV2 = reflect.TypeOf((*pref.ProtoEnum)(nil)).Elem()
  133. messageIfaceV1 = reflect.TypeOf((*messageV1)(nil)).Elem()
  134. messageIfaceV2 = reflect.TypeOf((*pref.ProtoMessage)(nil)).Elem()
  135. byteType = reflect.TypeOf(byte(0))
  136. )
  137. // matchGoTypePBKind matches a Go type with the protobuf kind.
  138. //
  139. // This matcher deliberately supports a wider range of Go types than what
  140. // protoc-gen-go historically generated to be able to automatically wrap some
  141. // v1 messages generated by other forks of protoc-gen-go.
  142. func matchGoTypePBKind(t reflect.Type, k pref.Kind) converter {
  143. switch k {
  144. case pref.BoolKind:
  145. if t.Kind() == reflect.Bool {
  146. return makeScalarConverter(t, boolType)
  147. }
  148. case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
  149. if t.Kind() == reflect.Int32 {
  150. return makeScalarConverter(t, int32Type)
  151. }
  152. case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
  153. if t.Kind() == reflect.Int64 {
  154. return makeScalarConverter(t, int64Type)
  155. }
  156. case pref.Uint32Kind, pref.Fixed32Kind:
  157. if t.Kind() == reflect.Uint32 {
  158. return makeScalarConverter(t, uint32Type)
  159. }
  160. case pref.Uint64Kind, pref.Fixed64Kind:
  161. if t.Kind() == reflect.Uint64 {
  162. return makeScalarConverter(t, uint64Type)
  163. }
  164. case pref.FloatKind:
  165. if t.Kind() == reflect.Float32 {
  166. return makeScalarConverter(t, float32Type)
  167. }
  168. case pref.DoubleKind:
  169. if t.Kind() == reflect.Float64 {
  170. return makeScalarConverter(t, float64Type)
  171. }
  172. case pref.StringKind:
  173. if t.Kind() == reflect.String || (t.Kind() == reflect.Slice && t.Elem() == byteType) {
  174. return makeScalarConverter(t, stringType)
  175. }
  176. case pref.BytesKind:
  177. if t.Kind() == reflect.String || (t.Kind() == reflect.Slice && t.Elem() == byteType) {
  178. return makeScalarConverter(t, bytesType)
  179. }
  180. case pref.EnumKind:
  181. // Handle v2 enums, which must satisfy the proto.Enum interface.
  182. if t.Kind() != reflect.Ptr && t.Implements(enumIfaceV2) {
  183. // TODO: implement this.
  184. }
  185. // Handle v1 enums, which we identify as simply a named int32 type.
  186. if t.Kind() == reflect.Int32 && t.PkgPath() != "" {
  187. // TODO: need logic to wrap a legacy enum to implement this.
  188. }
  189. case pref.MessageKind, pref.GroupKind:
  190. // Handle v2 messages, which must satisfy the proto.Message interface.
  191. if t.Kind() == reflect.Ptr && t.Implements(messageIfaceV2) {
  192. // TODO: implement this.
  193. }
  194. // Handle v1 messages, which we need to wrap as a v2 message.
  195. if t.Kind() == reflect.Ptr && t.Implements(messageIfaceV1) {
  196. // TODO: need logic to wrap a legacy message.
  197. }
  198. }
  199. panic(fmt.Sprintf("invalid Go type %v for protobuf kind %v", t, k))
  200. }
  201. // converter provides functions for converting to/from Go reflect.Value types
  202. // and protobuf protoreflect.Value types.
  203. type converter struct {
  204. toPB func(reflect.Value) pref.Value
  205. toGo func(pref.Value) reflect.Value
  206. }
  207. func makeScalarConverter(goType, pbType reflect.Type) converter {
  208. return converter{
  209. toPB: func(v reflect.Value) pref.Value {
  210. if v.Type() != goType {
  211. panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), goType))
  212. }
  213. if goType.Kind() == reflect.String && pbType.Kind() == reflect.Slice && v.Len() == 0 {
  214. return pref.ValueOf([]byte(nil)) // ensure empty string is []byte(nil)
  215. }
  216. return pref.ValueOf(v.Convert(pbType).Interface())
  217. },
  218. toGo: func(v pref.Value) reflect.Value {
  219. rv := reflect.ValueOf(v.Interface())
  220. if rv.Type() != pbType {
  221. panic(fmt.Sprintf("invalid type: got %v, want %v", rv.Type(), pbType))
  222. }
  223. if pbType.Kind() == reflect.String && goType.Kind() == reflect.Slice && rv.Len() == 0 {
  224. return reflect.Zero(goType) // ensure empty string is []byte(nil)
  225. }
  226. return rv.Convert(goType)
  227. },
  228. }
  229. }