properties.go 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. // Copyright 2010 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. // +build use_golang_protobuf_v1
  5. package proto
  6. import (
  7. "reflect"
  8. "strconv"
  9. "strings"
  10. "sync"
  11. )
  12. // Constants that identify the encoding of a value on the wire.
  13. const (
  14. WireVarint = 0
  15. WireFixed32 = 5
  16. WireFixed64 = 1
  17. WireBytes = 2
  18. WireStartGroup = 3
  19. WireEndGroup = 4
  20. )
  21. // StructProperties represents properties for all the fields of a struct.
  22. type StructProperties struct {
  23. Prop []*Properties // properties for each field
  24. // OneofTypes contains information about the oneof fields in this message.
  25. // It is keyed by the original name of a field.
  26. OneofTypes map[string]*OneofProperties
  27. }
  28. // OneofProperties represents information about a specific field in a oneof.
  29. type OneofProperties struct {
  30. Type reflect.Type // pointer to generated struct type for this oneof field
  31. Field int // struct field number of the containing oneof in the message
  32. Prop *Properties
  33. }
  34. func (sp *StructProperties) Len() int { return len(sp.Prop) }
  35. func (sp *StructProperties) Less(i, j int) bool { return false }
  36. func (sp *StructProperties) Swap(i, j int) { return }
  37. // Properties represents the protocol-specific behavior of a single struct field.
  38. type Properties struct {
  39. Name string // name of the field, for error messages
  40. OrigName string // original name before protocol compiler (always set)
  41. JSONName string // name to use for JSON; determined by protoc
  42. Wire string
  43. WireType int
  44. Tag int
  45. Required bool
  46. Optional bool
  47. Repeated bool
  48. Packed bool // relevant for repeated primitives only
  49. Enum string // set for enum types only
  50. Proto3 bool // whether this is known to be a proto3 field
  51. Oneof bool // whether this is a oneof field
  52. Default string // default value
  53. HasDefault bool // whether an explicit default was provided
  54. MapKeyProp *Properties // set for map types only
  55. MapValProp *Properties // set for map types only
  56. }
  57. // String formats the properties in the protobuf struct field tag style.
  58. func (p *Properties) String() string {
  59. s := p.Wire
  60. s += "," + strconv.Itoa(p.Tag)
  61. if p.Required {
  62. s += ",req"
  63. }
  64. if p.Optional {
  65. s += ",opt"
  66. }
  67. if p.Repeated {
  68. s += ",rep"
  69. }
  70. if p.Packed {
  71. s += ",packed"
  72. }
  73. s += ",name=" + p.OrigName
  74. if p.JSONName != "" {
  75. s += ",json=" + p.JSONName
  76. }
  77. if p.Proto3 {
  78. s += ",proto3"
  79. }
  80. if p.Oneof {
  81. s += ",oneof"
  82. }
  83. if len(p.Enum) > 0 {
  84. s += ",enum=" + p.Enum
  85. }
  86. if p.HasDefault {
  87. s += ",def=" + p.Default
  88. }
  89. return s
  90. }
  91. // Parse populates p by parsing a string in the protobuf struct field tag style.
  92. func (p *Properties) Parse(tag string) {
  93. // For example: "bytes,49,opt,name=foo,def=hello!"
  94. for len(tag) > 0 {
  95. i := strings.IndexByte(tag, ',')
  96. if i < 0 {
  97. i = len(tag)
  98. }
  99. switch s := tag[:i]; {
  100. case strings.HasPrefix(s, "name="):
  101. p.OrigName = s[len("name="):]
  102. case strings.HasPrefix(s, "json="):
  103. p.JSONName = s[len("json="):]
  104. case strings.HasPrefix(s, "enum="):
  105. p.Enum = s[len("enum="):]
  106. case strings.Trim(s, "0123456789") == "":
  107. n, _ := strconv.ParseUint(s, 10, 32)
  108. p.Tag = int(n)
  109. case s == "opt":
  110. p.Optional = true
  111. case s == "req":
  112. p.Required = true
  113. case s == "rep":
  114. p.Repeated = true
  115. case s == "varint" || s == "zigzag32" || s == "zigzag64":
  116. p.Wire = s
  117. p.WireType = WireVarint
  118. case s == "fixed32":
  119. p.Wire = s
  120. p.WireType = WireFixed32
  121. case s == "fixed64":
  122. p.Wire = s
  123. p.WireType = WireFixed64
  124. case s == "bytes":
  125. p.Wire = s
  126. p.WireType = WireBytes
  127. case s == "group":
  128. p.Wire = s
  129. p.WireType = WireStartGroup
  130. case s == "packed":
  131. p.Packed = true
  132. case s == "proto3":
  133. p.Proto3 = true
  134. case s == "oneof":
  135. p.Oneof = true
  136. case strings.HasPrefix(s, "def="):
  137. // The default tag is special in that everything afterwards is the
  138. // default regardless of the presence of commas.
  139. p.HasDefault = true
  140. p.Default, i = tag[len("def="):], len(tag)
  141. }
  142. tag = strings.TrimPrefix(tag[i:], ",")
  143. }
  144. }
  145. // Init populates the properties from a protocol buffer struct tag.
  146. func (p *Properties) Init(typ reflect.Type, name, tag string, f *reflect.StructField) {
  147. p.init(typ, name, tag, f)
  148. }
  149. func (p *Properties) init(typ reflect.Type, name, tag string, f *reflect.StructField) {
  150. p.Name = name
  151. p.OrigName = name
  152. if tag == "" {
  153. return
  154. }
  155. p.Parse(tag)
  156. if typ != nil && typ.Kind() == reflect.Map {
  157. p.MapKeyProp = new(Properties)
  158. p.MapKeyProp.init(nil, "Key", f.Tag.Get("protobuf_key"), nil)
  159. p.MapValProp = new(Properties)
  160. p.MapValProp.init(nil, "Value", f.Tag.Get("protobuf_val"), nil)
  161. }
  162. }
  163. var propertiesCache sync.Map // map[reflect.Type]*StructProperties
  164. // GetProperties returns the list of properties for the type represented by t.
  165. // t must represent a generated struct type of a protocol message.
  166. func GetProperties(t reflect.Type) *StructProperties {
  167. if p, ok := propertiesCache.Load(t); ok {
  168. return p.(*StructProperties)
  169. }
  170. p, _ := propertiesCache.LoadOrStore(t, newProperties(t))
  171. return p.(*StructProperties)
  172. }
  173. func newProperties(t reflect.Type) *StructProperties {
  174. if t.Kind() != reflect.Struct {
  175. panic("proto: type must have kind struct")
  176. }
  177. prop := new(StructProperties)
  178. // Construct a list of properties for each field in the struct.
  179. for i := 0; i < t.NumField(); i++ {
  180. p := new(Properties)
  181. f := t.Field(i)
  182. p.init(f.Type, f.Name, f.Tag.Get("protobuf"), &f)
  183. if name := f.Tag.Get("protobuf_oneof"); name != "" {
  184. p.OrigName = name
  185. }
  186. prop.Prop = append(prop.Prop, p)
  187. }
  188. // Construct a mapping of oneof field names to properties.
  189. if oneofImplementors := oneofWrappers(t); len(oneofImplementors) > 0 {
  190. prop.OneofTypes = make(map[string]*OneofProperties)
  191. for _, wrapper := range oneofImplementors {
  192. p := &OneofProperties{
  193. Type: reflect.ValueOf(wrapper).Type(), // *T
  194. Prop: new(Properties),
  195. }
  196. f := p.Type.Elem().Field(0)
  197. p.Prop.Name = f.Name
  198. p.Prop.Parse(f.Tag.Get("protobuf"))
  199. // Determine the struct field that contains this oneof.
  200. // Each wrapper is assignable to exactly one parent field.
  201. for i := 0; i < t.NumField(); i++ {
  202. if p.Type.AssignableTo(t.Field(i).Type) {
  203. p.Field = i
  204. break
  205. }
  206. }
  207. prop.OneofTypes[p.Prop.OrigName] = p
  208. }
  209. }
  210. return prop
  211. }