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

544 lines
15 KiB

  1. // Go support for Protocol Buffers - Google's data interchange format
  2. //
  3. // Copyright 2010 The Go Authors. All rights reserved.
  4. // https://github.com/golang/protobuf
  5. //
  6. // Redistribution and use in source and binary forms, with or without
  7. // modification, are permitted provided that the following conditions are
  8. // met:
  9. //
  10. // * Redistributions of source code must retain the above copyright
  11. // notice, this list of conditions and the following disclaimer.
  12. // * Redistributions in binary form must reproduce the above
  13. // copyright notice, this list of conditions and the following disclaimer
  14. // in the documentation and/or other materials provided with the
  15. // distribution.
  16. // * Neither the name of Google Inc. nor the names of its
  17. // contributors may be used to endorse or promote products derived from
  18. // this software without specific prior written permission.
  19. //
  20. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  24. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  25. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  26. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  27. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  28. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  30. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. package proto
  32. /*
  33. * Routines for encoding data into the wire format for protocol buffers.
  34. */
  35. import (
  36. "fmt"
  37. "log"
  38. "reflect"
  39. "sort"
  40. "strconv"
  41. "strings"
  42. "sync"
  43. )
  44. const debug bool = false
  45. // Constants that identify the encoding of a value on the wire.
  46. const (
  47. WireVarint = 0
  48. WireFixed64 = 1
  49. WireBytes = 2
  50. WireStartGroup = 3
  51. WireEndGroup = 4
  52. WireFixed32 = 5
  53. )
  54. // tagMap is an optimization over map[int]int for typical protocol buffer
  55. // use-cases. Encoded protocol buffers are often in tag order with small tag
  56. // numbers.
  57. type tagMap struct {
  58. fastTags []int
  59. slowTags map[int]int
  60. }
  61. // tagMapFastLimit is the upper bound on the tag number that will be stored in
  62. // the tagMap slice rather than its map.
  63. const tagMapFastLimit = 1024
  64. func (p *tagMap) get(t int) (int, bool) {
  65. if t > 0 && t < tagMapFastLimit {
  66. if t >= len(p.fastTags) {
  67. return 0, false
  68. }
  69. fi := p.fastTags[t]
  70. return fi, fi >= 0
  71. }
  72. fi, ok := p.slowTags[t]
  73. return fi, ok
  74. }
  75. func (p *tagMap) put(t int, fi int) {
  76. if t > 0 && t < tagMapFastLimit {
  77. for len(p.fastTags) < t+1 {
  78. p.fastTags = append(p.fastTags, -1)
  79. }
  80. p.fastTags[t] = fi
  81. return
  82. }
  83. if p.slowTags == nil {
  84. p.slowTags = make(map[int]int)
  85. }
  86. p.slowTags[t] = fi
  87. }
  88. // StructProperties represents properties for all the fields of a struct.
  89. // decoderTags and decoderOrigNames should only be used by the decoder.
  90. type StructProperties struct {
  91. Prop []*Properties // properties for each field
  92. reqCount int // required count
  93. decoderTags tagMap // map from proto tag to struct field number
  94. decoderOrigNames map[string]int // map from original name to struct field number
  95. order []int // list of struct field numbers in tag order
  96. // OneofTypes contains information about the oneof fields in this message.
  97. // It is keyed by the original name of a field.
  98. OneofTypes map[string]*OneofProperties
  99. }
  100. // OneofProperties represents information about a specific field in a oneof.
  101. type OneofProperties struct {
  102. Type reflect.Type // pointer to generated struct type for this oneof field
  103. Field int // struct field number of the containing oneof in the message
  104. Prop *Properties
  105. }
  106. // Implement the sorting interface so we can sort the fields in tag order, as recommended by the spec.
  107. // See encode.go, (*Buffer).enc_struct.
  108. func (sp *StructProperties) Len() int { return len(sp.order) }
  109. func (sp *StructProperties) Less(i, j int) bool {
  110. return sp.Prop[sp.order[i]].Tag < sp.Prop[sp.order[j]].Tag
  111. }
  112. func (sp *StructProperties) Swap(i, j int) { sp.order[i], sp.order[j] = sp.order[j], sp.order[i] }
  113. // Properties represents the protocol-specific behavior of a single struct field.
  114. type Properties struct {
  115. Name string // name of the field, for error messages
  116. OrigName string // original name before protocol compiler (always set)
  117. JSONName string // name to use for JSON; determined by protoc
  118. Wire string
  119. WireType int
  120. Tag int
  121. Required bool
  122. Optional bool
  123. Repeated bool
  124. Packed bool // relevant for repeated primitives only
  125. Enum string // set for enum types only
  126. proto3 bool // whether this is known to be a proto3 field
  127. oneof bool // whether this is a oneof field
  128. Default string // default value
  129. HasDefault bool // whether an explicit default was provided
  130. stype reflect.Type // set for struct types only
  131. sprop *StructProperties // set for struct types only
  132. mtype reflect.Type // set for map types only
  133. MapKeyProp *Properties // set for map types only
  134. MapValProp *Properties // set for map types only
  135. }
  136. // String formats the properties in the protobuf struct field tag style.
  137. func (p *Properties) String() string {
  138. s := p.Wire
  139. s += ","
  140. s += strconv.Itoa(p.Tag)
  141. if p.Required {
  142. s += ",req"
  143. }
  144. if p.Optional {
  145. s += ",opt"
  146. }
  147. if p.Repeated {
  148. s += ",rep"
  149. }
  150. if p.Packed {
  151. s += ",packed"
  152. }
  153. s += ",name=" + p.OrigName
  154. if p.JSONName != p.OrigName {
  155. s += ",json=" + p.JSONName
  156. }
  157. if p.proto3 {
  158. s += ",proto3"
  159. }
  160. if p.oneof {
  161. s += ",oneof"
  162. }
  163. if len(p.Enum) > 0 {
  164. s += ",enum=" + p.Enum
  165. }
  166. if p.HasDefault {
  167. s += ",def=" + p.Default
  168. }
  169. return s
  170. }
  171. // Parse populates p by parsing a string in the protobuf struct field tag style.
  172. func (p *Properties) Parse(s string) {
  173. // "bytes,49,opt,name=foo,def=hello!"
  174. fields := strings.Split(s, ",") // breaks def=, but handled below.
  175. if len(fields) < 2 {
  176. log.Printf("proto: tag has too few fields: %q", s)
  177. return
  178. }
  179. p.Wire = fields[0]
  180. switch p.Wire {
  181. case "varint":
  182. p.WireType = WireVarint
  183. case "fixed32":
  184. p.WireType = WireFixed32
  185. case "fixed64":
  186. p.WireType = WireFixed64
  187. case "zigzag32":
  188. p.WireType = WireVarint
  189. case "zigzag64":
  190. p.WireType = WireVarint
  191. case "bytes", "group":
  192. p.WireType = WireBytes
  193. // no numeric converter for non-numeric types
  194. default:
  195. log.Printf("proto: tag has unknown wire type: %q", s)
  196. return
  197. }
  198. var err error
  199. p.Tag, err = strconv.Atoi(fields[1])
  200. if err != nil {
  201. return
  202. }
  203. outer:
  204. for i := 2; i < len(fields); i++ {
  205. f := fields[i]
  206. switch {
  207. case f == "req":
  208. p.Required = true
  209. case f == "opt":
  210. p.Optional = true
  211. case f == "rep":
  212. p.Repeated = true
  213. case f == "packed":
  214. p.Packed = true
  215. case strings.HasPrefix(f, "name="):
  216. p.OrigName = f[5:]
  217. case strings.HasPrefix(f, "json="):
  218. p.JSONName = f[5:]
  219. case strings.HasPrefix(f, "enum="):
  220. p.Enum = f[5:]
  221. case f == "proto3":
  222. p.proto3 = true
  223. case f == "oneof":
  224. p.oneof = true
  225. case strings.HasPrefix(f, "def="):
  226. p.HasDefault = true
  227. p.Default = f[4:] // rest of string
  228. if i+1 < len(fields) {
  229. // Commas aren't escaped, and def is always last.
  230. p.Default += "," + strings.Join(fields[i+1:], ",")
  231. break outer
  232. }
  233. }
  234. }
  235. }
  236. var protoMessageType = reflect.TypeOf((*Message)(nil)).Elem()
  237. // setFieldProps initializes the field properties for submessages and maps.
  238. func (p *Properties) setFieldProps(typ reflect.Type, f *reflect.StructField, lockGetProp bool) {
  239. switch t1 := typ; t1.Kind() {
  240. case reflect.Ptr:
  241. if t1.Elem().Kind() == reflect.Struct {
  242. p.stype = t1.Elem()
  243. }
  244. case reflect.Slice:
  245. if t2 := t1.Elem(); t2.Kind() == reflect.Ptr && t2.Elem().Kind() == reflect.Struct {
  246. p.stype = t2.Elem()
  247. }
  248. case reflect.Map:
  249. p.mtype = t1
  250. p.MapKeyProp = &Properties{}
  251. p.MapKeyProp.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp)
  252. p.MapValProp = &Properties{}
  253. vtype := p.mtype.Elem()
  254. if vtype.Kind() != reflect.Ptr && vtype.Kind() != reflect.Slice {
  255. // The value type is not a message (*T) or bytes ([]byte),
  256. // so we need encoders for the pointer to this type.
  257. vtype = reflect.PtrTo(vtype)
  258. }
  259. p.MapValProp.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp)
  260. }
  261. if p.stype != nil {
  262. if lockGetProp {
  263. p.sprop = GetProperties(p.stype)
  264. } else {
  265. p.sprop = getPropertiesLocked(p.stype)
  266. }
  267. }
  268. }
  269. var (
  270. marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem()
  271. )
  272. // Init populates the properties from a protocol buffer struct tag.
  273. func (p *Properties) Init(typ reflect.Type, name, tag string, f *reflect.StructField) {
  274. p.init(typ, name, tag, f, true)
  275. }
  276. func (p *Properties) init(typ reflect.Type, name, tag string, f *reflect.StructField, lockGetProp bool) {
  277. // "bytes,49,opt,def=hello!"
  278. p.Name = name
  279. p.OrigName = name
  280. if tag == "" {
  281. return
  282. }
  283. p.Parse(tag)
  284. p.setFieldProps(typ, f, lockGetProp)
  285. }
  286. var (
  287. propertiesMu sync.RWMutex
  288. propertiesMap = make(map[reflect.Type]*StructProperties)
  289. )
  290. // GetProperties returns the list of properties for the type represented by t.
  291. // t must represent a generated struct type of a protocol message.
  292. func GetProperties(t reflect.Type) *StructProperties {
  293. if t.Kind() != reflect.Struct {
  294. panic("proto: type must have kind struct")
  295. }
  296. // Most calls to GetProperties in a long-running program will be
  297. // retrieving details for types we have seen before.
  298. propertiesMu.RLock()
  299. sprop, ok := propertiesMap[t]
  300. propertiesMu.RUnlock()
  301. if ok {
  302. return sprop
  303. }
  304. propertiesMu.Lock()
  305. sprop = getPropertiesLocked(t)
  306. propertiesMu.Unlock()
  307. return sprop
  308. }
  309. type (
  310. oneofFuncsIface interface {
  311. XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{})
  312. }
  313. oneofWrappersIface interface {
  314. XXX_OneofWrappers() []interface{}
  315. }
  316. )
  317. // getPropertiesLocked requires that propertiesMu is held.
  318. func getPropertiesLocked(t reflect.Type) *StructProperties {
  319. if prop, ok := propertiesMap[t]; ok {
  320. return prop
  321. }
  322. prop := new(StructProperties)
  323. // in case of recursive protos, fill this in now.
  324. propertiesMap[t] = prop
  325. // build properties
  326. prop.Prop = make([]*Properties, t.NumField())
  327. prop.order = make([]int, t.NumField())
  328. for i := 0; i < t.NumField(); i++ {
  329. f := t.Field(i)
  330. p := new(Properties)
  331. name := f.Name
  332. p.init(f.Type, name, f.Tag.Get("protobuf"), &f, false)
  333. oneof := f.Tag.Get("protobuf_oneof") // special case
  334. if oneof != "" {
  335. // Oneof fields don't use the traditional protobuf tag.
  336. p.OrigName = oneof
  337. }
  338. prop.Prop[i] = p
  339. prop.order[i] = i
  340. if debug {
  341. print(i, " ", f.Name, " ", t.String(), " ")
  342. if p.Tag > 0 {
  343. print(p.String())
  344. }
  345. print("\n")
  346. }
  347. }
  348. // Re-order prop.order.
  349. sort.Sort(prop)
  350. var oots []interface{}
  351. switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) {
  352. case oneofFuncsIface:
  353. _, _, _, oots = m.XXX_OneofFuncs()
  354. case oneofWrappersIface:
  355. oots = m.XXX_OneofWrappers()
  356. }
  357. if len(oots) > 0 {
  358. // Interpret oneof metadata.
  359. prop.OneofTypes = make(map[string]*OneofProperties)
  360. for _, oot := range oots {
  361. oop := &OneofProperties{
  362. Type: reflect.ValueOf(oot).Type(), // *T
  363. Prop: new(Properties),
  364. }
  365. sft := oop.Type.Elem().Field(0)
  366. oop.Prop.Name = sft.Name
  367. oop.Prop.Parse(sft.Tag.Get("protobuf"))
  368. // There will be exactly one interface field that
  369. // this new value is assignable to.
  370. for i := 0; i < t.NumField(); i++ {
  371. f := t.Field(i)
  372. if f.Type.Kind() != reflect.Interface {
  373. continue
  374. }
  375. if !oop.Type.AssignableTo(f.Type) {
  376. continue
  377. }
  378. oop.Field = i
  379. break
  380. }
  381. prop.OneofTypes[oop.Prop.OrigName] = oop
  382. }
  383. }
  384. // build required counts
  385. // build tags
  386. reqCount := 0
  387. prop.decoderOrigNames = make(map[string]int)
  388. for i, p := range prop.Prop {
  389. if strings.HasPrefix(p.Name, "XXX_") {
  390. // Internal fields should not appear in tags/origNames maps.
  391. // They are handled specially when encoding and decoding.
  392. continue
  393. }
  394. if p.Required {
  395. reqCount++
  396. }
  397. prop.decoderTags.put(p.Tag, i)
  398. prop.decoderOrigNames[p.OrigName] = i
  399. }
  400. prop.reqCount = reqCount
  401. return prop
  402. }
  403. // A global registry of enum types.
  404. // The generated code will register the generated maps by calling RegisterEnum.
  405. var enumValueMaps = make(map[string]map[string]int32)
  406. // RegisterEnum is called from the generated code to install the enum descriptor
  407. // maps into the global table to aid parsing text format protocol buffers.
  408. func RegisterEnum(typeName string, unusedNameMap map[int32]string, valueMap map[string]int32) {
  409. if _, ok := enumValueMaps[typeName]; ok {
  410. panic("proto: duplicate enum registered: " + typeName)
  411. }
  412. enumValueMaps[typeName] = valueMap
  413. }
  414. // EnumValueMap returns the mapping from names to integers of the
  415. // enum type enumType, or a nil if not found.
  416. func EnumValueMap(enumType string) map[string]int32 {
  417. return enumValueMaps[enumType]
  418. }
  419. // A registry of all linked message types.
  420. // The string is a fully-qualified proto name ("pkg.Message").
  421. var (
  422. protoTypedNils = make(map[string]Message) // a map from proto names to typed nil pointers
  423. protoMapTypes = make(map[string]reflect.Type) // a map from proto names to map types
  424. revProtoTypes = make(map[reflect.Type]string)
  425. )
  426. // RegisterType is called from generated code and maps from the fully qualified
  427. // proto name to the type (pointer to struct) of the protocol buffer.
  428. func RegisterType(x Message, name string) {
  429. if _, ok := protoTypedNils[name]; ok {
  430. // TODO: Some day, make this a panic.
  431. log.Printf("proto: duplicate proto type registered: %s", name)
  432. return
  433. }
  434. t := reflect.TypeOf(x)
  435. if v := reflect.ValueOf(x); v.Kind() == reflect.Ptr && v.Pointer() == 0 {
  436. // Generated code always calls RegisterType with nil x.
  437. // This check is just for extra safety.
  438. protoTypedNils[name] = x
  439. } else {
  440. protoTypedNils[name] = reflect.Zero(t).Interface().(Message)
  441. }
  442. revProtoTypes[t] = name
  443. }
  444. // RegisterMapType is called from generated code and maps from the fully qualified
  445. // proto name to the native map type of the proto map definition.
  446. func RegisterMapType(x interface{}, name string) {
  447. if reflect.TypeOf(x).Kind() != reflect.Map {
  448. panic(fmt.Sprintf("RegisterMapType(%T, %q); want map", x, name))
  449. }
  450. if _, ok := protoMapTypes[name]; ok {
  451. log.Printf("proto: duplicate proto type registered: %s", name)
  452. return
  453. }
  454. t := reflect.TypeOf(x)
  455. protoMapTypes[name] = t
  456. revProtoTypes[t] = name
  457. }
  458. // MessageName returns the fully-qualified proto name for the given message type.
  459. func MessageName(x Message) string {
  460. type xname interface {
  461. XXX_MessageName() string
  462. }
  463. if m, ok := x.(xname); ok {
  464. return m.XXX_MessageName()
  465. }
  466. return revProtoTypes[reflect.TypeOf(x)]
  467. }
  468. // MessageType returns the message type (pointer to struct) for a named message.
  469. // The type is not guaranteed to implement proto.Message if the name refers to a
  470. // map entry.
  471. func MessageType(name string) reflect.Type {
  472. if t, ok := protoTypedNils[name]; ok {
  473. return reflect.TypeOf(t)
  474. }
  475. return protoMapTypes[name]
  476. }
  477. // A registry of all linked proto files.
  478. var (
  479. protoFiles = make(map[string][]byte) // file name => fileDescriptor
  480. )
  481. // RegisterFile is called from generated code and maps from the
  482. // full file name of a .proto file to its compressed FileDescriptorProto.
  483. func RegisterFile(filename string, fileDescriptor []byte) {
  484. protoFiles[filename] = fileDescriptor
  485. }
  486. // FileDescriptor returns the compressed FileDescriptorProto for a .proto file.
  487. func FileDescriptor(filename string) []byte { return protoFiles[filename] }