123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604 |
- // Go support for Protocol Buffers - Google's data interchange format
- //
- // Copyright 2010 The Go Authors. All rights reserved.
- // https://github.com/golang/protobuf
- //
- // Redistribution and use in source and binary forms, with or without
- // modification, are permitted provided that the following conditions are
- // met:
- //
- // * Redistributions of source code must retain the above copyright
- // notice, this list of conditions and the following disclaimer.
- // * Redistributions in binary form must reproduce the above
- // copyright notice, this list of conditions and the following disclaimer
- // in the documentation and/or other materials provided with the
- // distribution.
- // * Neither the name of Google Inc. nor the names of its
- // contributors may be used to endorse or promote products derived from
- // this software without specific prior written permission.
- //
- // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- package proto
- /*
- * Types and routines for supporting protocol buffer extensions.
- */
- import (
- "errors"
- "fmt"
- "io"
- "reflect"
- "strconv"
- "sync"
- )
- // ErrMissingExtension is the error returned by GetExtension if the named extension is not in the message.
- var ErrMissingExtension = errors.New("proto: missing extension")
- // ExtensionRange represents a range of message extensions for a protocol buffer.
- // Used in code generated by the protocol compiler.
- type ExtensionRange struct {
- Start, End int32 // both inclusive
- }
- // extendableProto is an interface implemented by any protocol buffer generated by the current
- // proto compiler that may be extended.
- type extendableProto interface {
- Message
- ExtensionRangeArray() []ExtensionRange
- extensionsWrite() map[int32]Extension
- extensionsRead() (map[int32]Extension, sync.Locker)
- }
- // extendableProtoV1 is an interface implemented by a protocol buffer generated by the previous
- // version of the proto compiler that may be extended.
- type extendableProtoV1 interface {
- Message
- ExtensionRangeArray() []ExtensionRange
- ExtensionMap() map[int32]Extension
- }
- // extensionAdapter is a wrapper around extendableProtoV1 that implements extendableProto.
- type extensionAdapter struct {
- extendableProtoV1
- }
- func (e extensionAdapter) extensionsWrite() map[int32]Extension {
- return e.ExtensionMap()
- }
- func (e extensionAdapter) extensionsRead() (map[int32]Extension, sync.Locker) {
- return e.ExtensionMap(), notLocker{}
- }
- // notLocker is a sync.Locker whose Lock and Unlock methods are nops.
- type notLocker struct{}
- func (n notLocker) Lock() {}
- func (n notLocker) Unlock() {}
- // extendable returns the extendableProto interface for the given generated proto message.
- // If the proto message has the old extension format, it returns a wrapper that implements
- // the extendableProto interface.
- func extendable(p interface{}) (extendableProto, error) {
- switch p := p.(type) {
- case extendableProto:
- if isNilPtr(p) {
- return nil, fmt.Errorf("proto: nil %T is not extendable", p)
- }
- return p, nil
- case extendableProtoV1:
- if isNilPtr(p) {
- return nil, fmt.Errorf("proto: nil %T is not extendable", p)
- }
- return extensionAdapter{p}, nil
- case extensionsBytes:
- return slowExtensionAdapter{p}, nil
- }
- // Don't allocate a specific error containing %T:
- // this is the hot path for Clone and MarshalText.
- return nil, errNotExtendable
- }
- var errNotExtendable = errors.New("proto: not an extendable proto.Message")
- func isNilPtr(x interface{}) bool {
- v := reflect.ValueOf(x)
- return v.Kind() == reflect.Ptr && v.IsNil()
- }
- // XXX_InternalExtensions is an internal representation of proto extensions.
- //
- // Each generated message struct type embeds an anonymous XXX_InternalExtensions field,
- // thus gaining the unexported 'extensions' method, which can be called only from the proto package.
- //
- // The methods of XXX_InternalExtensions are not concurrency safe in general,
- // but calls to logically read-only methods such as has and get may be executed concurrently.
- type XXX_InternalExtensions struct {
- // The struct must be indirect so that if a user inadvertently copies a
- // generated message and its embedded XXX_InternalExtensions, they
- // avoid the mayhem of a copied mutex.
- //
- // The mutex serializes all logically read-only operations to p.extensionMap.
- // It is up to the client to ensure that write operations to p.extensionMap are
- // mutually exclusive with other accesses.
- p *struct {
- mu sync.Mutex
- extensionMap map[int32]Extension
- }
- }
- // extensionsWrite returns the extension map, creating it on first use.
- func (e *XXX_InternalExtensions) extensionsWrite() map[int32]Extension {
- if e.p == nil {
- e.p = new(struct {
- mu sync.Mutex
- extensionMap map[int32]Extension
- })
- e.p.extensionMap = make(map[int32]Extension)
- }
- return e.p.extensionMap
- }
- // extensionsRead returns the extensions map for read-only use. It may be nil.
- // The caller must hold the returned mutex's lock when accessing Elements within the map.
- func (e *XXX_InternalExtensions) extensionsRead() (map[int32]Extension, sync.Locker) {
- if e.p == nil {
- return nil, nil
- }
- return e.p.extensionMap, &e.p.mu
- }
- // ExtensionDesc represents an extension specification.
- // Used in generated code from the protocol compiler.
- type ExtensionDesc struct {
- ExtendedType Message // nil pointer to the type that is being extended
- ExtensionType interface{} // nil pointer to the extension type
- Field int32 // field number
- Name string // fully-qualified name of extension, for text formatting
- Tag string // protobuf tag style
- Filename string // name of the file in which the extension is defined
- }
- func (ed *ExtensionDesc) repeated() bool {
- t := reflect.TypeOf(ed.ExtensionType)
- return t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8
- }
- // Extension represents an extension in a message.
- type Extension struct {
- // When an extension is stored in a message using SetExtension
- // only desc and value are set. When the message is marshaled
- // enc will be set to the encoded form of the message.
- //
- // When a message is unmarshaled and contains extensions, each
- // extension will have only enc set. When such an extension is
- // accessed using GetExtension (or GetExtensions) desc and value
- // will be set.
- desc *ExtensionDesc
- value interface{}
- enc []byte
- }
- // SetRawExtension is for testing only.
- func SetRawExtension(base Message, id int32, b []byte) {
- if ebase, ok := base.(extensionsBytes); ok {
- clearExtension(base, id)
- ext := ebase.GetExtensions()
- *ext = append(*ext, b...)
- return
- }
- epb, err := extendable(base)
- if err != nil {
- return
- }
- extmap := epb.extensionsWrite()
- extmap[id] = Extension{enc: b}
- }
- // isExtensionField returns true iff the given field number is in an extension range.
- func isExtensionField(pb extendableProto, field int32) bool {
- for _, er := range pb.ExtensionRangeArray() {
- if er.Start <= field && field <= er.End {
- return true
- }
- }
- return false
- }
- // checkExtensionTypes checks that the given extension is valid for pb.
- func checkExtensionTypes(pb extendableProto, extension *ExtensionDesc) error {
- var pbi interface{} = pb
- // Check the extended type.
- if ea, ok := pbi.(extensionAdapter); ok {
- pbi = ea.extendableProtoV1
- }
- if ea, ok := pbi.(slowExtensionAdapter); ok {
- pbi = ea.extensionsBytes
- }
- if a, b := reflect.TypeOf(pbi), reflect.TypeOf(extension.ExtendedType); a != b {
- return fmt.Errorf("proto: bad extended type; %v does not extend %v", b, a)
- }
- // Check the range.
- if !isExtensionField(pb, extension.Field) {
- return errors.New("proto: bad extension number; not in declared ranges")
- }
- return nil
- }
- // extPropKey is sufficient to uniquely identify an extension.
- type extPropKey struct {
- base reflect.Type
- field int32
- }
- var extProp = struct {
- sync.RWMutex
- m map[extPropKey]*Properties
- }{
- m: make(map[extPropKey]*Properties),
- }
- func extensionProperties(ed *ExtensionDesc) *Properties {
- key := extPropKey{base: reflect.TypeOf(ed.ExtendedType), field: ed.Field}
- extProp.RLock()
- if prop, ok := extProp.m[key]; ok {
- extProp.RUnlock()
- return prop
- }
- extProp.RUnlock()
- extProp.Lock()
- defer extProp.Unlock()
- // Check again.
- if prop, ok := extProp.m[key]; ok {
- return prop
- }
- prop := new(Properties)
- prop.Init(reflect.TypeOf(ed.ExtensionType), "unknown_name", ed.Tag, nil)
- extProp.m[key] = prop
- return prop
- }
- // HasExtension returns whether the given extension is present in pb.
- func HasExtension(pb Message, extension *ExtensionDesc) bool {
- if epb, doki := pb.(extensionsBytes); doki {
- ext := epb.GetExtensions()
- buf := *ext
- o := 0
- for o < len(buf) {
- tag, n := DecodeVarint(buf[o:])
- fieldNum := int32(tag >> 3)
- if int32(fieldNum) == extension.Field {
- return true
- }
- wireType := int(tag & 0x7)
- o += n
- l, err := size(buf[o:], wireType)
- if err != nil {
- return false
- }
- o += l
- }
- return false
- }
- // TODO: Check types, field numbers, etc.?
- epb, err := extendable(pb)
- if err != nil {
- return false
- }
- extmap, mu := epb.extensionsRead()
- if extmap == nil {
- return false
- }
- mu.Lock()
- _, ok := extmap[extension.Field]
- mu.Unlock()
- return ok
- }
- // ClearExtension removes the given extension from pb.
- func ClearExtension(pb Message, extension *ExtensionDesc) {
- clearExtension(pb, extension.Field)
- }
- func clearExtension(pb Message, fieldNum int32) {
- if epb, ok := pb.(extensionsBytes); ok {
- offset := 0
- for offset != -1 {
- offset = deleteExtension(epb, fieldNum, offset)
- }
- return
- }
- epb, err := extendable(pb)
- if err != nil {
- return
- }
- // TODO: Check types, field numbers, etc.?
- extmap := epb.extensionsWrite()
- delete(extmap, fieldNum)
- }
- // GetExtension retrieves a proto2 extended field from pb.
- //
- // If the descriptor is type complete (i.e., ExtensionDesc.ExtensionType is non-nil),
- // then GetExtension parses the encoded field and returns a Go value of the specified type.
- // If the field is not present, then the default value is returned (if one is specified),
- // otherwise ErrMissingExtension is reported.
- //
- // If the descriptor is not type complete (i.e., ExtensionDesc.ExtensionType is nil),
- // then GetExtension returns the raw encoded bytes of the field extension.
- func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) {
- if epb, doki := pb.(extensionsBytes); doki {
- ext := epb.GetExtensions()
- return decodeExtensionFromBytes(extension, *ext)
- }
- epb, err := extendable(pb)
- if err != nil {
- return nil, err
- }
- if extension.ExtendedType != nil {
- // can only check type if this is a complete descriptor
- if cerr := checkExtensionTypes(epb, extension); cerr != nil {
- return nil, cerr
- }
- }
- emap, mu := epb.extensionsRead()
- if emap == nil {
- return defaultExtensionValue(extension)
- }
- mu.Lock()
- defer mu.Unlock()
- e, ok := emap[extension.Field]
- if !ok {
- // defaultExtensionValue returns the default value or
- // ErrMissingExtension if there is no default.
- return defaultExtensionValue(extension)
- }
- if e.value != nil {
- // Already decoded. Check the descriptor, though.
- if e.desc != extension {
- // This shouldn't happen. If it does, it means that
- // GetExtension was called twice with two different
- // descriptors with the same field number.
- return nil, errors.New("proto: descriptor conflict")
- }
- return e.value, nil
- }
- if extension.ExtensionType == nil {
- // incomplete descriptor
- return e.enc, nil
- }
- v, err := decodeExtension(e.enc, extension)
- if err != nil {
- return nil, err
- }
- // Remember the decoded version and drop the encoded version.
- // That way it is safe to mutate what we return.
- e.value = v
- e.desc = extension
- e.enc = nil
- emap[extension.Field] = e
- return e.value, nil
- }
- // defaultExtensionValue returns the default value for extension.
- // If no default for an extension is defined ErrMissingExtension is returned.
- func defaultExtensionValue(extension *ExtensionDesc) (interface{}, error) {
- if extension.ExtensionType == nil {
- // incomplete descriptor, so no default
- return nil, ErrMissingExtension
- }
- t := reflect.TypeOf(extension.ExtensionType)
- props := extensionProperties(extension)
- sf, _, err := fieldDefault(t, props)
- if err != nil {
- return nil, err
- }
- if sf == nil || sf.value == nil {
- // There is no default value.
- return nil, ErrMissingExtension
- }
- if t.Kind() != reflect.Ptr {
- // We do not need to return a Ptr, we can directly return sf.value.
- return sf.value, nil
- }
- // We need to return an interface{} that is a pointer to sf.value.
- value := reflect.New(t).Elem()
- value.Set(reflect.New(value.Type().Elem()))
- if sf.kind == reflect.Int32 {
- // We may have an int32 or an enum, but the underlying data is int32.
- // Since we can't set an int32 into a non int32 reflect.value directly
- // set it as a int32.
- value.Elem().SetInt(int64(sf.value.(int32)))
- } else {
- value.Elem().Set(reflect.ValueOf(sf.value))
- }
- return value.Interface(), nil
- }
- // decodeExtension decodes an extension encoded in b.
- func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) {
- t := reflect.TypeOf(extension.ExtensionType)
- unmarshal := typeUnmarshaler(t, extension.Tag)
- // t is a pointer to a struct, pointer to basic type or a slice.
- // Allocate space to store the pointer/slice.
- value := reflect.New(t).Elem()
- var err error
- for {
- x, n := decodeVarint(b)
- if n == 0 {
- return nil, io.ErrUnexpectedEOF
- }
- b = b[n:]
- wire := int(x) & 7
- b, err = unmarshal(b, valToPointer(value.Addr()), wire)
- if err != nil {
- return nil, err
- }
- if len(b) == 0 {
- break
- }
- }
- return value.Interface(), nil
- }
- // GetExtensions returns a slice of the extensions present in pb that are also listed in es.
- // The returned slice has the same length as es; missing extensions will appear as nil elements.
- func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, err error) {
- epb, err := extendable(pb)
- if err != nil {
- return nil, err
- }
- extensions = make([]interface{}, len(es))
- for i, e := range es {
- extensions[i], err = GetExtension(epb, e)
- if err == ErrMissingExtension {
- err = nil
- }
- if err != nil {
- return
- }
- }
- return
- }
- // ExtensionDescs returns a new slice containing pb's extension descriptors, in undefined order.
- // For non-registered extensions, ExtensionDescs returns an incomplete descriptor containing
- // just the Field field, which defines the extension's field number.
- func ExtensionDescs(pb Message) ([]*ExtensionDesc, error) {
- epb, err := extendable(pb)
- if err != nil {
- return nil, err
- }
- registeredExtensions := RegisteredExtensions(pb)
- emap, mu := epb.extensionsRead()
- if emap == nil {
- return nil, nil
- }
- mu.Lock()
- defer mu.Unlock()
- extensions := make([]*ExtensionDesc, 0, len(emap))
- for extid, e := range emap {
- desc := e.desc
- if desc == nil {
- desc = registeredExtensions[extid]
- if desc == nil {
- desc = &ExtensionDesc{Field: extid}
- }
- }
- extensions = append(extensions, desc)
- }
- return extensions, nil
- }
- // SetExtension sets the specified extension of pb to the specified value.
- func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error {
- if epb, ok := pb.(extensionsBytes); ok {
- newb, err := encodeExtension(extension, value)
- if err != nil {
- return err
- }
- bb := epb.GetExtensions()
- *bb = append(*bb, newb...)
- return nil
- }
- epb, err := extendable(pb)
- if err != nil {
- return err
- }
- if err := checkExtensionTypes(epb, extension); err != nil {
- return err
- }
- typ := reflect.TypeOf(extension.ExtensionType)
- if typ != reflect.TypeOf(value) {
- return errors.New("proto: bad extension value type")
- }
- // nil extension values need to be caught early, because the
- // encoder can't distinguish an ErrNil due to a nil extension
- // from an ErrNil due to a missing field. Extensions are
- // always optional, so the encoder would just swallow the error
- // and drop all the extensions from the encoded message.
- if reflect.ValueOf(value).IsNil() {
- return fmt.Errorf("proto: SetExtension called with nil value of type %T", value)
- }
- extmap := epb.extensionsWrite()
- extmap[extension.Field] = Extension{desc: extension, value: value}
- return nil
- }
- // ClearAllExtensions clears all extensions from pb.
- func ClearAllExtensions(pb Message) {
- if epb, doki := pb.(extensionsBytes); doki {
- ext := epb.GetExtensions()
- *ext = []byte{}
- return
- }
- epb, err := extendable(pb)
- if err != nil {
- return
- }
- m := epb.extensionsWrite()
- for k := range m {
- delete(m, k)
- }
- }
- // A global registry of extensions.
- // The generated code will register the generated descriptors by calling RegisterExtension.
- var extensionMaps = make(map[reflect.Type]map[int32]*ExtensionDesc)
- // RegisterExtension is called from the generated code.
- func RegisterExtension(desc *ExtensionDesc) {
- st := reflect.TypeOf(desc.ExtendedType).Elem()
- m := extensionMaps[st]
- if m == nil {
- m = make(map[int32]*ExtensionDesc)
- extensionMaps[st] = m
- }
- if _, ok := m[desc.Field]; ok {
- panic("proto: duplicate extension registered: " + st.String() + " " + strconv.Itoa(int(desc.Field)))
- }
- m[desc.Field] = desc
- }
- // RegisteredExtensions returns a map of the registered extensions of a
- // protocol buffer struct, indexed by the extension number.
- // The argument pb should be a nil pointer to the struct type.
- func RegisteredExtensions(pb Message) map[int32]*ExtensionDesc {
- return extensionMaps[reflect.TypeOf(pb).Elem()]
- }
|