blob: 0dfcb538e8f1b1bfa609ec3c28f04d8b0cdad155 [file] [log] [blame]
David K. Bainbridge215e0242017-09-05 23:18:24 -07001// 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
32package proto
33
34/*
35 * Types and routines for supporting protocol buffer extensions.
36 */
37
38import (
39 "errors"
40 "fmt"
41 "reflect"
42 "strconv"
43 "sync"
44)
45
46// ErrMissingExtension is the error returned by GetExtension if the named extension is not in the message.
47var ErrMissingExtension = errors.New("proto: missing extension")
48
49// ExtensionRange represents a range of message extensions for a protocol buffer.
50// Used in code generated by the protocol compiler.
51type ExtensionRange struct {
52 Start, End int32 // both inclusive
53}
54
55// extendableProto is an interface implemented by any protocol buffer generated by the current
56// proto compiler that may be extended.
57type extendableProto interface {
58 Message
59 ExtensionRangeArray() []ExtensionRange
60 extensionsWrite() map[int32]Extension
61 extensionsRead() (map[int32]Extension, sync.Locker)
62}
63
64// extendableProtoV1 is an interface implemented by a protocol buffer generated by the previous
65// version of the proto compiler that may be extended.
66type extendableProtoV1 interface {
67 Message
68 ExtensionRangeArray() []ExtensionRange
69 ExtensionMap() map[int32]Extension
70}
71
72type extensionsBytes interface {
73 Message
74 ExtensionRangeArray() []ExtensionRange
75 GetExtensions() *[]byte
76}
77
78// extensionAdapter is a wrapper around extendableProtoV1 that implements extendableProto.
79type extensionAdapter struct {
80 extendableProtoV1
81}
82
83func (e extensionAdapter) extensionsWrite() map[int32]Extension {
84 return e.ExtensionMap()
85}
86
87func (e extensionAdapter) extensionsRead() (map[int32]Extension, sync.Locker) {
88 return e.ExtensionMap(), notLocker{}
89}
90
91// notLocker is a sync.Locker whose Lock and Unlock methods are nops.
92type notLocker struct{}
93
94func (n notLocker) Lock() {}
95func (n notLocker) Unlock() {}
96
97// extendable returns the extendableProto interface for the given generated proto message.
98// If the proto message has the old extension format, it returns a wrapper that implements
99// the extendableProto interface.
100func extendable(p interface{}) (extendableProto, bool) {
101 if ep, ok := p.(extendableProto); ok {
102 return ep, ok
103 }
104 if ep, ok := p.(extendableProtoV1); ok {
105 return extensionAdapter{ep}, ok
106 }
107 return nil, false
108}
109
110// XXX_InternalExtensions is an internal representation of proto extensions.
111//
112// Each generated message struct type embeds an anonymous XXX_InternalExtensions field,
113// thus gaining the unexported 'extensions' method, which can be called only from the proto package.
114//
115// The methods of XXX_InternalExtensions are not concurrency safe in general,
116// but calls to logically read-only methods such as has and get may be executed concurrently.
117type XXX_InternalExtensions struct {
118 // The struct must be indirect so that if a user inadvertently copies a
119 // generated message and its embedded XXX_InternalExtensions, they
120 // avoid the mayhem of a copied mutex.
121 //
122 // The mutex serializes all logically read-only operations to p.extensionMap.
123 // It is up to the client to ensure that write operations to p.extensionMap are
124 // mutually exclusive with other accesses.
125 p *struct {
126 mu sync.Mutex
127 extensionMap map[int32]Extension
128 }
129}
130
131// extensionsWrite returns the extension map, creating it on first use.
132func (e *XXX_InternalExtensions) extensionsWrite() map[int32]Extension {
133 if e.p == nil {
134 e.p = new(struct {
135 mu sync.Mutex
136 extensionMap map[int32]Extension
137 })
138 e.p.extensionMap = make(map[int32]Extension)
139 }
140 return e.p.extensionMap
141}
142
143// extensionsRead returns the extensions map for read-only use. It may be nil.
144// The caller must hold the returned mutex's lock when accessing Elements within the map.
145func (e *XXX_InternalExtensions) extensionsRead() (map[int32]Extension, sync.Locker) {
146 if e.p == nil {
147 return nil, nil
148 }
149 return e.p.extensionMap, &e.p.mu
150}
151
152type extensionRange interface {
153 Message
154 ExtensionRangeArray() []ExtensionRange
155}
156
157var extendableProtoType = reflect.TypeOf((*extendableProto)(nil)).Elem()
158var extendableProtoV1Type = reflect.TypeOf((*extendableProtoV1)(nil)).Elem()
159var extendableBytesType = reflect.TypeOf((*extensionsBytes)(nil)).Elem()
160var extensionRangeType = reflect.TypeOf((*extensionRange)(nil)).Elem()
161
162// ExtensionDesc represents an extension specification.
163// Used in generated code from the protocol compiler.
164type ExtensionDesc struct {
165 ExtendedType Message // nil pointer to the type that is being extended
166 ExtensionType interface{} // nil pointer to the extension type
167 Field int32 // field number
168 Name string // fully-qualified name of extension, for text formatting
169 Tag string // protobuf tag style
170 Filename string // name of the file in which the extension is defined
171}
172
173func (ed *ExtensionDesc) repeated() bool {
174 t := reflect.TypeOf(ed.ExtensionType)
175 return t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8
176}
177
178// Extension represents an extension in a message.
179type Extension struct {
180 // When an extension is stored in a message using SetExtension
181 // only desc and value are set. When the message is marshaled
182 // enc will be set to the encoded form of the message.
183 //
184 // When a message is unmarshaled and contains extensions, each
185 // extension will have only enc set. When such an extension is
186 // accessed using GetExtension (or GetExtensions) desc and value
187 // will be set.
188 desc *ExtensionDesc
189 value interface{}
190 enc []byte
191}
192
193// SetRawExtension is for testing only.
194func SetRawExtension(base Message, id int32, b []byte) {
195 if ebase, ok := base.(extensionsBytes); ok {
196 clearExtension(base, id)
197 ext := ebase.GetExtensions()
198 *ext = append(*ext, b...)
199 return
200 }
201 epb, ok := extendable(base)
202 if !ok {
203 return
204 }
205 extmap := epb.extensionsWrite()
206 extmap[id] = Extension{enc: b}
207}
208
209// isExtensionField returns true iff the given field number is in an extension range.
210func isExtensionField(pb extensionRange, field int32) bool {
211 for _, er := range pb.ExtensionRangeArray() {
212 if er.Start <= field && field <= er.End {
213 return true
214 }
215 }
216 return false
217}
218
219// checkExtensionTypes checks that the given extension is valid for pb.
220func checkExtensionTypes(pb extendableProto, extension *ExtensionDesc) error {
221 var pbi interface{} = pb
222 // Check the extended type.
223 if ea, ok := pbi.(extensionAdapter); ok {
224 pbi = ea.extendableProtoV1
225 }
226 if a, b := reflect.TypeOf(pbi), reflect.TypeOf(extension.ExtendedType); a != b {
227 return errors.New("proto: bad extended type; " + b.String() + " does not extend " + a.String())
228 }
229 // Check the range.
230 if !isExtensionField(pb, extension.Field) {
231 return errors.New("proto: bad extension number; not in declared ranges")
232 }
233 return nil
234}
235
236// extPropKey is sufficient to uniquely identify an extension.
237type extPropKey struct {
238 base reflect.Type
239 field int32
240}
241
242var extProp = struct {
243 sync.RWMutex
244 m map[extPropKey]*Properties
245}{
246 m: make(map[extPropKey]*Properties),
247}
248
249func extensionProperties(ed *ExtensionDesc) *Properties {
250 key := extPropKey{base: reflect.TypeOf(ed.ExtendedType), field: ed.Field}
251
252 extProp.RLock()
253 if prop, ok := extProp.m[key]; ok {
254 extProp.RUnlock()
255 return prop
256 }
257 extProp.RUnlock()
258
259 extProp.Lock()
260 defer extProp.Unlock()
261 // Check again.
262 if prop, ok := extProp.m[key]; ok {
263 return prop
264 }
265
266 prop := new(Properties)
267 prop.Init(reflect.TypeOf(ed.ExtensionType), "unknown_name", ed.Tag, nil)
268 extProp.m[key] = prop
269 return prop
270}
271
272// encode encodes any unmarshaled (unencoded) extensions in e.
273func encodeExtensions(e *XXX_InternalExtensions) error {
274 m, mu := e.extensionsRead()
275 if m == nil {
276 return nil // fast path
277 }
278 mu.Lock()
279 defer mu.Unlock()
280 return encodeExtensionsMap(m)
281}
282
283// encode encodes any unmarshaled (unencoded) extensions in e.
284func encodeExtensionsMap(m map[int32]Extension) error {
285 for k, e := range m {
286 if e.value == nil || e.desc == nil {
287 // Extension is only in its encoded form.
288 continue
289 }
290
291 // We don't skip extensions that have an encoded form set,
292 // because the extension value may have been mutated after
293 // the last time this function was called.
294
295 et := reflect.TypeOf(e.desc.ExtensionType)
296 props := extensionProperties(e.desc)
297
298 p := NewBuffer(nil)
299 // If e.value has type T, the encoder expects a *struct{ X T }.
300 // Pass a *T with a zero field and hope it all works out.
301 x := reflect.New(et)
302 x.Elem().Set(reflect.ValueOf(e.value))
303 if err := props.enc(p, props, toStructPointer(x)); err != nil {
304 return err
305 }
306 e.enc = p.buf
307 m[k] = e
308 }
309 return nil
310}
311
312func extensionsSize(e *XXX_InternalExtensions) (n int) {
313 m, mu := e.extensionsRead()
314 if m == nil {
315 return 0
316 }
317 mu.Lock()
318 defer mu.Unlock()
319 return extensionsMapSize(m)
320}
321
322func extensionsMapSize(m map[int32]Extension) (n int) {
323 for _, e := range m {
324 if e.value == nil || e.desc == nil {
325 // Extension is only in its encoded form.
326 n += len(e.enc)
327 continue
328 }
329
330 // We don't skip extensions that have an encoded form set,
331 // because the extension value may have been mutated after
332 // the last time this function was called.
333
334 et := reflect.TypeOf(e.desc.ExtensionType)
335 props := extensionProperties(e.desc)
336
337 // If e.value has type T, the encoder expects a *struct{ X T }.
338 // Pass a *T with a zero field and hope it all works out.
339 x := reflect.New(et)
340 x.Elem().Set(reflect.ValueOf(e.value))
341 n += props.size(props, toStructPointer(x))
342 }
343 return
344}
345
346// HasExtension returns whether the given extension is present in pb.
347func HasExtension(pb Message, extension *ExtensionDesc) bool {
348 if epb, doki := pb.(extensionsBytes); doki {
349 ext := epb.GetExtensions()
350 buf := *ext
351 o := 0
352 for o < len(buf) {
353 tag, n := DecodeVarint(buf[o:])
354 fieldNum := int32(tag >> 3)
355 if int32(fieldNum) == extension.Field {
356 return true
357 }
358 wireType := int(tag & 0x7)
359 o += n
360 l, err := size(buf[o:], wireType)
361 if err != nil {
362 return false
363 }
364 o += l
365 }
366 return false
367 }
368 // TODO: Check types, field numbers, etc.?
369 epb, ok := extendable(pb)
370 if !ok {
371 return false
372 }
373 extmap, mu := epb.extensionsRead()
374 if extmap == nil {
375 return false
376 }
377 mu.Lock()
378 _, ok = extmap[extension.Field]
379 mu.Unlock()
380 return ok
381}
382
383func deleteExtension(pb extensionsBytes, theFieldNum int32, offset int) int {
384 ext := pb.GetExtensions()
385 for offset < len(*ext) {
386 tag, n1 := DecodeVarint((*ext)[offset:])
387 fieldNum := int32(tag >> 3)
388 wireType := int(tag & 0x7)
389 n2, err := size((*ext)[offset+n1:], wireType)
390 if err != nil {
391 panic(err)
392 }
393 newOffset := offset + n1 + n2
394 if fieldNum == theFieldNum {
395 *ext = append((*ext)[:offset], (*ext)[newOffset:]...)
396 return offset
397 }
398 offset = newOffset
399 }
400 return -1
401}
402
403// ClearExtension removes the given extension from pb.
404func ClearExtension(pb Message, extension *ExtensionDesc) {
405 clearExtension(pb, extension.Field)
406}
407
408func clearExtension(pb Message, fieldNum int32) {
409 if epb, doki := pb.(extensionsBytes); doki {
410 offset := 0
411 for offset != -1 {
412 offset = deleteExtension(epb, fieldNum, offset)
413 }
414 return
415 }
416 epb, ok := extendable(pb)
417 if !ok {
418 return
419 }
420 // TODO: Check types, field numbers, etc.?
421 extmap := epb.extensionsWrite()
422 delete(extmap, fieldNum)
423}
424
425// GetExtension parses and returns the given extension of pb.
426// If the extension is not present and has no default value it returns ErrMissingExtension.
427func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) {
428 if epb, doki := pb.(extensionsBytes); doki {
429 ext := epb.GetExtensions()
430 o := 0
431 for o < len(*ext) {
432 tag, n := DecodeVarint((*ext)[o:])
433 fieldNum := int32(tag >> 3)
434 wireType := int(tag & 0x7)
435 l, err := size((*ext)[o+n:], wireType)
436 if err != nil {
437 return nil, err
438 }
439 if int32(fieldNum) == extension.Field {
440 v, err := decodeExtension((*ext)[o:o+n+l], extension)
441 if err != nil {
442 return nil, err
443 }
444 return v, nil
445 }
446 o += n + l
447 }
448 return defaultExtensionValue(extension)
449 }
450 epb, ok := extendable(pb)
451 if !ok {
452 return nil, errors.New("proto: not an extendable proto")
453 }
454 if err := checkExtensionTypes(epb, extension); err != nil {
455 return nil, err
456 }
457
458 emap, mu := epb.extensionsRead()
459 if emap == nil {
460 return defaultExtensionValue(extension)
461 }
462 mu.Lock()
463 defer mu.Unlock()
464 e, ok := emap[extension.Field]
465 if !ok {
466 // defaultExtensionValue returns the default value or
467 // ErrMissingExtension if there is no default.
468 return defaultExtensionValue(extension)
469 }
470
471 if e.value != nil {
472 // Already decoded. Check the descriptor, though.
473 if e.desc != extension {
474 // This shouldn't happen. If it does, it means that
475 // GetExtension was called twice with two different
476 // descriptors with the same field number.
477 return nil, errors.New("proto: descriptor conflict")
478 }
479 return e.value, nil
480 }
481
482 v, err := decodeExtension(e.enc, extension)
483 if err != nil {
484 return nil, err
485 }
486
487 // Remember the decoded version and drop the encoded version.
488 // That way it is safe to mutate what we return.
489 e.value = v
490 e.desc = extension
491 e.enc = nil
492 emap[extension.Field] = e
493 return e.value, nil
494}
495
496// defaultExtensionValue returns the default value for extension.
497// If no default for an extension is defined ErrMissingExtension is returned.
498func defaultExtensionValue(extension *ExtensionDesc) (interface{}, error) {
499 t := reflect.TypeOf(extension.ExtensionType)
500 props := extensionProperties(extension)
501
502 sf, _, err := fieldDefault(t, props)
503 if err != nil {
504 return nil, err
505 }
506
507 if sf == nil || sf.value == nil {
508 // There is no default value.
509 return nil, ErrMissingExtension
510 }
511
512 if t.Kind() != reflect.Ptr {
513 // We do not need to return a Ptr, we can directly return sf.value.
514 return sf.value, nil
515 }
516
517 // We need to return an interface{} that is a pointer to sf.value.
518 value := reflect.New(t).Elem()
519 value.Set(reflect.New(value.Type().Elem()))
520 if sf.kind == reflect.Int32 {
521 // We may have an int32 or an enum, but the underlying data is int32.
522 // Since we can't set an int32 into a non int32 reflect.value directly
523 // set it as a int32.
524 value.Elem().SetInt(int64(sf.value.(int32)))
525 } else {
526 value.Elem().Set(reflect.ValueOf(sf.value))
527 }
528 return value.Interface(), nil
529}
530
531// decodeExtension decodes an extension encoded in b.
532func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) {
533 o := NewBuffer(b)
534
535 t := reflect.TypeOf(extension.ExtensionType)
536
537 props := extensionProperties(extension)
538
539 // t is a pointer to a struct, pointer to basic type or a slice.
540 // Allocate a "field" to store the pointer/slice itself; the
541 // pointer/slice will be stored here. We pass
542 // the address of this field to props.dec.
543 // This passes a zero field and a *t and lets props.dec
544 // interpret it as a *struct{ x t }.
545 value := reflect.New(t).Elem()
546
547 for {
548 // Discard wire type and field number varint. It isn't needed.
549 if _, err := o.DecodeVarint(); err != nil {
550 return nil, err
551 }
552
553 if err := props.dec(o, props, toStructPointer(value.Addr())); err != nil {
554 return nil, err
555 }
556
557 if o.index >= len(o.buf) {
558 break
559 }
560 }
561 return value.Interface(), nil
562}
563
564// GetExtensions returns a slice of the extensions present in pb that are also listed in es.
565// The returned slice has the same length as es; missing extensions will appear as nil elements.
566func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, err error) {
567 extensions = make([]interface{}, len(es))
568 for i, e := range es {
569 extensions[i], err = GetExtension(pb, e)
570 if err == ErrMissingExtension {
571 err = nil
572 }
573 if err != nil {
574 return
575 }
576 }
577 return
578}
579
580// ExtensionDescs returns a new slice containing pb's extension descriptors, in undefined order.
581// For non-registered extensions, ExtensionDescs returns an incomplete descriptor containing
582// just the Field field, which defines the extension's field number.
583func ExtensionDescs(pb Message) ([]*ExtensionDesc, error) {
584 epb, ok := extendable(pb)
585 if !ok {
586 return nil, fmt.Errorf("proto: %T is not an extendable proto.Message", pb)
587 }
588 registeredExtensions := RegisteredExtensions(pb)
589
590 emap, mu := epb.extensionsRead()
591 if emap == nil {
592 return nil, nil
593 }
594 mu.Lock()
595 defer mu.Unlock()
596 extensions := make([]*ExtensionDesc, 0, len(emap))
597 for extid, e := range emap {
598 desc := e.desc
599 if desc == nil {
600 desc = registeredExtensions[extid]
601 if desc == nil {
602 desc = &ExtensionDesc{Field: extid}
603 }
604 }
605
606 extensions = append(extensions, desc)
607 }
608 return extensions, nil
609}
610
611// SetExtension sets the specified extension of pb to the specified value.
612func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error {
613 if epb, doki := pb.(extensionsBytes); doki {
614 ClearExtension(pb, extension)
615 ext := epb.GetExtensions()
616 et := reflect.TypeOf(extension.ExtensionType)
617 props := extensionProperties(extension)
618 p := NewBuffer(nil)
619 x := reflect.New(et)
620 x.Elem().Set(reflect.ValueOf(value))
621 if err := props.enc(p, props, toStructPointer(x)); err != nil {
622 return err
623 }
624 *ext = append(*ext, p.buf...)
625 return nil
626 }
627 epb, ok := extendable(pb)
628 if !ok {
629 return errors.New("proto: not an extendable proto")
630 }
631 if err := checkExtensionTypes(epb, extension); err != nil {
632 return err
633 }
634 typ := reflect.TypeOf(extension.ExtensionType)
635 if typ != reflect.TypeOf(value) {
636 return errors.New("proto: bad extension value type")
637 }
638 // nil extension values need to be caught early, because the
639 // encoder can't distinguish an ErrNil due to a nil extension
640 // from an ErrNil due to a missing field. Extensions are
641 // always optional, so the encoder would just swallow the error
642 // and drop all the extensions from the encoded message.
643 if reflect.ValueOf(value).IsNil() {
644 return fmt.Errorf("proto: SetExtension called with nil value of type %T", value)
645 }
646
647 extmap := epb.extensionsWrite()
648 extmap[extension.Field] = Extension{desc: extension, value: value}
649 return nil
650}
651
652// ClearAllExtensions clears all extensions from pb.
653func ClearAllExtensions(pb Message) {
654 if epb, doki := pb.(extensionsBytes); doki {
655 ext := epb.GetExtensions()
656 *ext = []byte{}
657 return
658 }
659 epb, ok := extendable(pb)
660 if !ok {
661 return
662 }
663 m := epb.extensionsWrite()
664 for k := range m {
665 delete(m, k)
666 }
667}
668
669// A global registry of extensions.
670// The generated code will register the generated descriptors by calling RegisterExtension.
671
672var extensionMaps = make(map[reflect.Type]map[int32]*ExtensionDesc)
673
674// RegisterExtension is called from the generated code.
675func RegisterExtension(desc *ExtensionDesc) {
676 st := reflect.TypeOf(desc.ExtendedType).Elem()
677 m := extensionMaps[st]
678 if m == nil {
679 m = make(map[int32]*ExtensionDesc)
680 extensionMaps[st] = m
681 }
682 if _, ok := m[desc.Field]; ok {
683 panic("proto: duplicate extension registered: " + st.String() + " " + strconv.Itoa(int(desc.Field)))
684 }
685 m[desc.Field] = desc
686}
687
688// RegisteredExtensions returns a map of the registered extensions of a
689// protocol buffer struct, indexed by the extension number.
690// The argument pb should be a nil pointer to the struct type.
691func RegisteredExtensions(pb Message) map[int32]*ExtensionDesc {
692 return extensionMaps[reflect.TypeOf(pb).Elem()]
693}