properties.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649
  1. // Go support for Protocol Buffers - Google's data interchange format
  2. //
  3. // Copyright 2010 The Go Authors. All rights reserved.
  4. // http://code.google.com/p/goprotobuf/
  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. "os"
  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. const startSize = 10 // initial slice/string sizes
  55. // Encoders are defined in encode.go
  56. // An encoder outputs the full representation of a field, including its
  57. // tag and encoder type.
  58. type encoder func(p *Buffer, prop *Properties, base structPointer) error
  59. // A valueEncoder encodes a single integer in a particular encoding.
  60. type valueEncoder func(o *Buffer, x uint64) error
  61. // Sizers are defined in encode.go
  62. // A sizer returns the encoded size of a field, including its tag and encoder
  63. // type.
  64. type sizer func(prop *Properties, base structPointer) int
  65. // A valueSizer returns the encoded size of a single integer in a particular
  66. // encoding.
  67. type valueSizer func(x uint64) int
  68. // Decoders are defined in decode.go
  69. // A decoder creates a value from its wire representation.
  70. // Unrecognized subelements are saved in unrec.
  71. type decoder func(p *Buffer, prop *Properties, base structPointer) error
  72. // A valueDecoder decodes a single integer in a particular encoding.
  73. type valueDecoder func(o *Buffer) (x uint64, err error)
  74. // tagMap is an optimization over map[int]int for typical protocol buffer
  75. // use-cases. Encoded protocol buffers are often in tag order with small tag
  76. // numbers.
  77. type tagMap struct {
  78. fastTags []int
  79. slowTags map[int]int
  80. }
  81. // tagMapFastLimit is the upper bound on the tag number that will be stored in
  82. // the tagMap slice rather than its map.
  83. const tagMapFastLimit = 1024
  84. func (p *tagMap) get(t int) (int, bool) {
  85. if t > 0 && t < tagMapFastLimit {
  86. if t >= len(p.fastTags) {
  87. return 0, false
  88. }
  89. fi := p.fastTags[t]
  90. return fi, fi >= 0
  91. }
  92. fi, ok := p.slowTags[t]
  93. return fi, ok
  94. }
  95. func (p *tagMap) put(t int, fi int) {
  96. if t > 0 && t < tagMapFastLimit {
  97. for len(p.fastTags) < t+1 {
  98. p.fastTags = append(p.fastTags, -1)
  99. }
  100. p.fastTags[t] = fi
  101. return
  102. }
  103. if p.slowTags == nil {
  104. p.slowTags = make(map[int]int)
  105. }
  106. p.slowTags[t] = fi
  107. }
  108. // StructProperties represents properties for all the fields of a struct.
  109. // decoderTags and decoderOrigNames should only be used by the decoder.
  110. type StructProperties struct {
  111. Prop []*Properties // properties for each field
  112. reqCount int // required count
  113. decoderTags tagMap // map from proto tag to struct field number
  114. decoderOrigNames map[string]int // map from original name to struct field number
  115. order []int // list of struct field numbers in tag order
  116. unrecField field // field id of the XXX_unrecognized []byte field
  117. extendable bool // is this an extendable proto
  118. }
  119. // Implement the sorting interface so we can sort the fields in tag order, as recommended by the spec.
  120. // See encode.go, (*Buffer).enc_struct.
  121. func (sp *StructProperties) Len() int { return len(sp.order) }
  122. func (sp *StructProperties) Less(i, j int) bool {
  123. return sp.Prop[sp.order[i]].Tag < sp.Prop[sp.order[j]].Tag
  124. }
  125. func (sp *StructProperties) Swap(i, j int) { sp.order[i], sp.order[j] = sp.order[j], sp.order[i] }
  126. // Properties represents the protocol-specific behavior of a single struct field.
  127. type Properties struct {
  128. Name string // name of the field, for error messages
  129. OrigName string // original name before protocol compiler (always set)
  130. Wire string
  131. WireType int
  132. Tag int
  133. Required bool
  134. Optional bool
  135. Repeated bool
  136. Packed bool // relevant for repeated primitives only
  137. Enum string // set for enum types only
  138. Default string // default value
  139. def_uint64 uint64
  140. enc encoder
  141. valEnc valueEncoder // set for bool and numeric types only
  142. field field
  143. tagcode []byte // encoding of EncodeVarint((Tag<<3)|WireType)
  144. tagbuf [8]byte
  145. stype reflect.Type // set for struct types only
  146. sprop *StructProperties // set for struct types only
  147. isMarshaler bool
  148. isUnmarshaler bool
  149. size sizer
  150. valSize valueSizer // set for bool and numeric types only
  151. dec decoder
  152. valDec valueDecoder // set for bool and numeric types only
  153. // If this is a packable field, this will be the decoder for the packed version of the field.
  154. packedDec decoder
  155. }
  156. // String formats the properties in the protobuf struct field tag style.
  157. func (p *Properties) String() string {
  158. s := p.Wire
  159. s = ","
  160. s += strconv.Itoa(p.Tag)
  161. if p.Required {
  162. s += ",req"
  163. }
  164. if p.Optional {
  165. s += ",opt"
  166. }
  167. if p.Repeated {
  168. s += ",rep"
  169. }
  170. if p.Packed {
  171. s += ",packed"
  172. }
  173. if p.OrigName != p.Name {
  174. s += ",name=" + p.OrigName
  175. }
  176. if len(p.Enum) > 0 {
  177. s += ",enum=" + p.Enum
  178. }
  179. if len(p.Default) > 0 {
  180. s += ",def=" + p.Default
  181. }
  182. return s
  183. }
  184. // Parse populates p by parsing a string in the protobuf struct field tag style.
  185. func (p *Properties) Parse(s string) {
  186. // "bytes,49,opt,name=foo,def=hello!"
  187. fields := strings.Split(s, ",") // breaks def=, but handled below.
  188. if len(fields) < 2 {
  189. fmt.Fprintf(os.Stderr, "proto: tag has too few fields: %q\n", s)
  190. return
  191. }
  192. p.Wire = fields[0]
  193. switch p.Wire {
  194. case "varint":
  195. p.WireType = WireVarint
  196. p.valEnc = (*Buffer).EncodeVarint
  197. p.valDec = (*Buffer).DecodeVarint
  198. p.valSize = sizeVarint
  199. case "fixed32":
  200. p.WireType = WireFixed32
  201. p.valEnc = (*Buffer).EncodeFixed32
  202. p.valDec = (*Buffer).DecodeFixed32
  203. p.valSize = sizeFixed32
  204. case "fixed64":
  205. p.WireType = WireFixed64
  206. p.valEnc = (*Buffer).EncodeFixed64
  207. p.valDec = (*Buffer).DecodeFixed64
  208. p.valSize = sizeFixed64
  209. case "zigzag32":
  210. p.WireType = WireVarint
  211. p.valEnc = (*Buffer).EncodeZigzag32
  212. p.valDec = (*Buffer).DecodeZigzag32
  213. p.valSize = sizeZigzag32
  214. case "zigzag64":
  215. p.WireType = WireVarint
  216. p.valEnc = (*Buffer).EncodeZigzag64
  217. p.valDec = (*Buffer).DecodeZigzag64
  218. p.valSize = sizeZigzag64
  219. case "bytes", "group":
  220. p.WireType = WireBytes
  221. // no numeric converter for non-numeric types
  222. default:
  223. fmt.Fprintf(os.Stderr, "proto: tag has unknown wire type: %q\n", s)
  224. return
  225. }
  226. var err error
  227. p.Tag, err = strconv.Atoi(fields[1])
  228. if err != nil {
  229. return
  230. }
  231. for i := 2; i < len(fields); i++ {
  232. f := fields[i]
  233. switch {
  234. case f == "req":
  235. p.Required = true
  236. case f == "opt":
  237. p.Optional = true
  238. case f == "rep":
  239. p.Repeated = true
  240. case f == "packed":
  241. p.Packed = true
  242. case strings.HasPrefix(f, "name="):
  243. p.OrigName = f[5:]
  244. case strings.HasPrefix(f, "enum="):
  245. p.Enum = f[5:]
  246. case strings.HasPrefix(f, "def="):
  247. p.Default = f[4:] // rest of string
  248. if i+1 < len(fields) {
  249. // Commas aren't escaped, and def is always last.
  250. p.Default += "," + strings.Join(fields[i+1:], ",")
  251. break
  252. }
  253. }
  254. }
  255. }
  256. func logNoSliceEnc(t1, t2 reflect.Type) {
  257. fmt.Fprintf(os.Stderr, "proto: no slice oenc for %T = []%T\n", t1, t2)
  258. }
  259. var protoMessageType = reflect.TypeOf((*Message)(nil)).Elem()
  260. // Initialize the fields for encoding and decoding.
  261. func (p *Properties) setEncAndDec(typ reflect.Type, lockGetProp bool) {
  262. p.enc = nil
  263. p.dec = nil
  264. p.size = nil
  265. switch t1 := typ; t1.Kind() {
  266. default:
  267. fmt.Fprintf(os.Stderr, "proto: no coders for %T\n", t1)
  268. case reflect.Ptr:
  269. switch t2 := t1.Elem(); t2.Kind() {
  270. default:
  271. fmt.Fprintf(os.Stderr, "proto: no encoder function for %T -> %T\n", t1, t2)
  272. break
  273. case reflect.Bool:
  274. p.enc = (*Buffer).enc_bool
  275. p.dec = (*Buffer).dec_bool
  276. p.size = size_bool
  277. case reflect.Int32, reflect.Uint32:
  278. p.enc = (*Buffer).enc_int32
  279. p.dec = (*Buffer).dec_int32
  280. p.size = size_int32
  281. case reflect.Int64, reflect.Uint64:
  282. p.enc = (*Buffer).enc_int64
  283. p.dec = (*Buffer).dec_int64
  284. p.size = size_int64
  285. case reflect.Float32:
  286. p.enc = (*Buffer).enc_int32 // can just treat them as bits
  287. p.dec = (*Buffer).dec_int32
  288. p.size = size_int32
  289. case reflect.Float64:
  290. p.enc = (*Buffer).enc_int64 // can just treat them as bits
  291. p.dec = (*Buffer).dec_int64
  292. p.size = size_int64
  293. case reflect.String:
  294. p.enc = (*Buffer).enc_string
  295. p.dec = (*Buffer).dec_string
  296. p.size = size_string
  297. case reflect.Struct:
  298. p.stype = t1.Elem()
  299. p.isMarshaler = isMarshaler(t1)
  300. p.isUnmarshaler = isUnmarshaler(t1)
  301. if p.Wire == "bytes" {
  302. p.enc = (*Buffer).enc_struct_message
  303. p.dec = (*Buffer).dec_struct_message
  304. p.size = size_struct_message
  305. } else {
  306. p.enc = (*Buffer).enc_struct_group
  307. p.dec = (*Buffer).dec_struct_group
  308. p.size = size_struct_group
  309. }
  310. }
  311. case reflect.Slice:
  312. switch t2 := t1.Elem(); t2.Kind() {
  313. default:
  314. logNoSliceEnc(t1, t2)
  315. break
  316. case reflect.Bool:
  317. if p.Packed {
  318. p.enc = (*Buffer).enc_slice_packed_bool
  319. p.size = size_slice_packed_bool
  320. } else {
  321. p.enc = (*Buffer).enc_slice_bool
  322. p.size = size_slice_bool
  323. }
  324. p.dec = (*Buffer).dec_slice_bool
  325. p.packedDec = (*Buffer).dec_slice_packed_bool
  326. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  327. switch t2.Bits() {
  328. case 32:
  329. if p.Packed {
  330. p.enc = (*Buffer).enc_slice_packed_int32
  331. p.size = size_slice_packed_int32
  332. } else {
  333. p.enc = (*Buffer).enc_slice_int32
  334. p.size = size_slice_int32
  335. }
  336. p.dec = (*Buffer).dec_slice_int32
  337. p.packedDec = (*Buffer).dec_slice_packed_int32
  338. case 64:
  339. if p.Packed {
  340. p.enc = (*Buffer).enc_slice_packed_int64
  341. p.size = size_slice_packed_int64
  342. } else {
  343. p.enc = (*Buffer).enc_slice_int64
  344. p.size = size_slice_int64
  345. }
  346. p.dec = (*Buffer).dec_slice_int64
  347. p.packedDec = (*Buffer).dec_slice_packed_int64
  348. case 8:
  349. if t2.Kind() == reflect.Uint8 {
  350. p.enc = (*Buffer).enc_slice_byte
  351. p.dec = (*Buffer).dec_slice_byte
  352. p.size = size_slice_byte
  353. }
  354. default:
  355. logNoSliceEnc(t1, t2)
  356. break
  357. }
  358. case reflect.Float32, reflect.Float64:
  359. switch t2.Bits() {
  360. case 32:
  361. // can just treat them as bits
  362. if p.Packed {
  363. p.enc = (*Buffer).enc_slice_packed_int32
  364. p.size = size_slice_packed_int32
  365. } else {
  366. p.enc = (*Buffer).enc_slice_int32
  367. p.size = size_slice_int32
  368. }
  369. p.dec = (*Buffer).dec_slice_int32
  370. p.packedDec = (*Buffer).dec_slice_packed_int32
  371. case 64:
  372. // can just treat them as bits
  373. if p.Packed {
  374. p.enc = (*Buffer).enc_slice_packed_int64
  375. p.size = size_slice_packed_int64
  376. } else {
  377. p.enc = (*Buffer).enc_slice_int64
  378. p.size = size_slice_int64
  379. }
  380. p.dec = (*Buffer).dec_slice_int64
  381. p.packedDec = (*Buffer).dec_slice_packed_int64
  382. default:
  383. logNoSliceEnc(t1, t2)
  384. break
  385. }
  386. case reflect.String:
  387. p.enc = (*Buffer).enc_slice_string
  388. p.dec = (*Buffer).dec_slice_string
  389. p.size = size_slice_string
  390. case reflect.Ptr:
  391. switch t3 := t2.Elem(); t3.Kind() {
  392. default:
  393. fmt.Fprintf(os.Stderr, "proto: no ptr oenc for %T -> %T -> %T\n", t1, t2, t3)
  394. break
  395. case reflect.Struct:
  396. p.stype = t2.Elem()
  397. p.isMarshaler = isMarshaler(t2)
  398. p.isUnmarshaler = isUnmarshaler(t2)
  399. if p.Wire == "bytes" {
  400. p.enc = (*Buffer).enc_slice_struct_message
  401. p.dec = (*Buffer).dec_slice_struct_message
  402. p.size = size_slice_struct_message
  403. } else {
  404. p.enc = (*Buffer).enc_slice_struct_group
  405. p.dec = (*Buffer).dec_slice_struct_group
  406. p.size = size_slice_struct_group
  407. }
  408. }
  409. case reflect.Slice:
  410. switch t2.Elem().Kind() {
  411. default:
  412. fmt.Fprintf(os.Stderr, "proto: no slice elem oenc for %T -> %T -> %T\n", t1, t2, t2.Elem())
  413. break
  414. case reflect.Uint8:
  415. p.enc = (*Buffer).enc_slice_slice_byte
  416. p.dec = (*Buffer).dec_slice_slice_byte
  417. p.size = size_slice_slice_byte
  418. }
  419. }
  420. }
  421. // precalculate tag code
  422. wire := p.WireType
  423. if p.Packed {
  424. wire = WireBytes
  425. }
  426. x := uint32(p.Tag)<<3 | uint32(wire)
  427. i := 0
  428. for i = 0; x > 127; i++ {
  429. p.tagbuf[i] = 0x80 | uint8(x&0x7F)
  430. x >>= 7
  431. }
  432. p.tagbuf[i] = uint8(x)
  433. p.tagcode = p.tagbuf[0 : i+1]
  434. if p.stype != nil {
  435. if lockGetProp {
  436. p.sprop = GetProperties(p.stype)
  437. } else {
  438. p.sprop = getPropertiesLocked(p.stype)
  439. }
  440. }
  441. }
  442. var (
  443. marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem()
  444. unmarshalerType = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
  445. )
  446. // isMarshaler reports whether type t implements Marshaler.
  447. func isMarshaler(t reflect.Type) bool {
  448. // We're checking for (likely) pointer-receiver methods
  449. // so if t is not a pointer, something is very wrong.
  450. // The calls above only invoke isMarshaler on pointer types.
  451. if t.Kind() != reflect.Ptr {
  452. panic("proto: misuse of isMarshaler")
  453. }
  454. return t.Implements(marshalerType)
  455. }
  456. // isUnmarshaler reports whether type t implements Unmarshaler.
  457. func isUnmarshaler(t reflect.Type) bool {
  458. // We're checking for (likely) pointer-receiver methods
  459. // so if t is not a pointer, something is very wrong.
  460. // The calls above only invoke isUnmarshaler on pointer types.
  461. if t.Kind() != reflect.Ptr {
  462. panic("proto: misuse of isUnmarshaler")
  463. }
  464. return t.Implements(unmarshalerType)
  465. }
  466. // Init populates the properties from a protocol buffer struct tag.
  467. func (p *Properties) Init(typ reflect.Type, name, tag string, f *reflect.StructField) {
  468. p.init(typ, name, tag, f, true)
  469. }
  470. func (p *Properties) init(typ reflect.Type, name, tag string, f *reflect.StructField, lockGetProp bool) {
  471. // "bytes,49,opt,def=hello!"
  472. p.Name = name
  473. p.OrigName = name
  474. if f != nil {
  475. p.field = toField(f)
  476. }
  477. if tag == "" {
  478. return
  479. }
  480. p.Parse(tag)
  481. p.setEncAndDec(typ, lockGetProp)
  482. }
  483. var (
  484. mutex sync.Mutex
  485. propertiesMap = make(map[reflect.Type]*StructProperties)
  486. )
  487. // GetProperties returns the list of properties for the type represented by t.
  488. func GetProperties(t reflect.Type) *StructProperties {
  489. mutex.Lock()
  490. sprop := getPropertiesLocked(t)
  491. mutex.Unlock()
  492. return sprop
  493. }
  494. // getPropertiesLocked requires that mutex is held.
  495. func getPropertiesLocked(t reflect.Type) *StructProperties {
  496. if prop, ok := propertiesMap[t]; ok {
  497. if collectStats {
  498. stats.Chit++
  499. }
  500. return prop
  501. }
  502. if collectStats {
  503. stats.Cmiss++
  504. }
  505. prop := new(StructProperties)
  506. // in case of recursive protos, fill this in now.
  507. propertiesMap[t] = prop
  508. // build properties
  509. prop.extendable = reflect.PtrTo(t).Implements(extendableProtoType)
  510. prop.unrecField = invalidField
  511. prop.Prop = make([]*Properties, t.NumField())
  512. prop.order = make([]int, t.NumField())
  513. for i := 0; i < t.NumField(); i++ {
  514. f := t.Field(i)
  515. p := new(Properties)
  516. name := f.Name
  517. p.init(f.Type, name, f.Tag.Get("protobuf"), &f, false)
  518. if f.Name == "XXX_extensions" { // special case
  519. p.enc = (*Buffer).enc_map
  520. p.dec = nil // not needed
  521. p.size = size_map
  522. }
  523. if f.Name == "XXX_unrecognized" { // special case
  524. prop.unrecField = toField(&f)
  525. }
  526. prop.Prop[i] = p
  527. prop.order[i] = i
  528. if debug {
  529. print(i, " ", f.Name, " ", t.String(), " ")
  530. if p.Tag > 0 {
  531. print(p.String())
  532. }
  533. print("\n")
  534. }
  535. if p.enc == nil && !strings.HasPrefix(f.Name, "XXX_") {
  536. fmt.Fprintln(os.Stderr, "proto: no encoder for", f.Name, f.Type.String(), "[GetProperties]")
  537. }
  538. }
  539. // Re-order prop.order.
  540. sort.Sort(prop)
  541. // build required counts
  542. // build tags
  543. reqCount := 0
  544. prop.decoderOrigNames = make(map[string]int)
  545. for i, p := range prop.Prop {
  546. if strings.HasPrefix(p.Name, "XXX_") {
  547. // Internal fields should not appear in tags/origNames maps.
  548. // They are handled specially when encoding and decoding.
  549. continue
  550. }
  551. if p.Required {
  552. reqCount++
  553. }
  554. prop.decoderTags.put(p.Tag, i)
  555. prop.decoderOrigNames[p.OrigName] = i
  556. }
  557. prop.reqCount = reqCount
  558. return prop
  559. }
  560. // Return the Properties object for the x[0]'th field of the structure.
  561. func propByIndex(t reflect.Type, x []int) *Properties {
  562. if len(x) != 1 {
  563. fmt.Fprintf(os.Stderr, "proto: field index dimension %d (not 1) for type %s\n", len(x), t)
  564. return nil
  565. }
  566. prop := GetProperties(t)
  567. return prop.Prop[x[0]]
  568. }
  569. // Get the address and type of a pointer to a struct from an interface.
  570. func getbase(pb Message) (t reflect.Type, b structPointer, err error) {
  571. if pb == nil {
  572. err = ErrNil
  573. return
  574. }
  575. // get the reflect type of the pointer to the struct.
  576. t = reflect.TypeOf(pb)
  577. // get the address of the struct.
  578. value := reflect.ValueOf(pb)
  579. b = toStructPointer(value)
  580. return
  581. }
  582. // A global registry of enum types.
  583. // The generated code will register the generated maps by calling RegisterEnum.
  584. var enumValueMaps = make(map[string]map[string]int32)
  585. // RegisterEnum is called from the generated code to install the enum descriptor
  586. // maps into the global table to aid parsing text format protocol buffers.
  587. func RegisterEnum(typeName string, unusedNameMap map[int32]string, valueMap map[string]int32) {
  588. if _, ok := enumValueMaps[typeName]; ok {
  589. panic("proto: duplicate enum registered: " + typeName)
  590. }
  591. enumValueMaps[typeName] = valueMap
  592. }