另客网go项目公用的代码库

properties.go 15KB

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