blob: 5f62dff2474863632742a26a8c225590b47413f2 [file] [log] [blame]
Rob Pikeaaa3a622010-03-20 22:32:34 -07001// Go support for Protocol Buffers - Google's data interchange format
2//
David Symondsee6e9c52012-11-29 08:51:07 +11003// Copyright 2010 The Go Authors. All rights reserved.
David Symonds558f13f2014-11-24 10:28:53 +11004// https://github.com/golang/protobuf
Rob Pikeaaa3a622010-03-20 22:32:34 -07005//
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
Rob Pikeaaa3a622010-03-20 22:32:34 -070034/*
35 * Types and routines for supporting protocol buffer extensions.
36 */
37
38import (
Rob Pikea17fdd92011-11-02 12:43:05 -070039 "errors"
David Symonds82b6f0b2015-03-03 06:33:00 +110040 "fmt"
Rob Pikeaaa3a622010-03-20 22:32:34 -070041 "reflect"
David Symondse37856c2011-06-22 12:52:53 +100042 "strconv"
David Symonds29d5d392012-12-20 12:14:58 +110043 "sync"
Rob Pikeaaa3a622010-03-20 22:32:34 -070044)
45
David Symondsa7e9ef92012-01-18 18:27:58 +110046// ErrMissingExtension is the error returned by GetExtension if the named extension is not in the message.
47var ErrMissingExtension = errors.New("proto: missing extension")
48
Rob Pikeaaa3a622010-03-20 22:32:34 -070049// 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 that may be extended.
56type extendableProto interface {
David Symonds9f60f432012-06-14 09:45:25 +100057 Message
Rob Pikeaaa3a622010-03-20 22:32:34 -070058 ExtensionRangeArray() []ExtensionRange
David Symonds1d72f7a2011-08-19 18:28:52 +100059 ExtensionMap() map[int32]Extension
Rob Pikeaaa3a622010-03-20 22:32:34 -070060}
61
Russ Coxd4ce3f12012-09-12 10:36:26 +100062var extendableProtoType = reflect.TypeOf((*extendableProto)(nil)).Elem()
63
Rob Pikeaaa3a622010-03-20 22:32:34 -070064// ExtensionDesc represents an extension specification.
65// Used in generated code from the protocol compiler.
66type ExtensionDesc struct {
David Symonds9f60f432012-06-14 09:45:25 +100067 ExtendedType Message // nil pointer to the type that is being extended
Rob Pikeaaa3a622010-03-20 22:32:34 -070068 ExtensionType interface{} // nil pointer to the extension type
69 Field int32 // field number
David Symondsc057ad52012-02-11 15:43:42 +110070 Name string // fully-qualified name of extension, for text formatting
David Symonds8935abf2011-07-04 15:53:16 +100071 Tag string // protobuf tag style
Rob Pikeaaa3a622010-03-20 22:32:34 -070072}
73
David Symonds61826da2012-05-05 09:31:28 +100074func (ed *ExtensionDesc) repeated() bool {
75 t := reflect.TypeOf(ed.ExtensionType)
76 return t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8
77}
78
David Symondsf511ee32012-09-06 11:36:28 +100079// Extension represents an extension in a message.
David Symonds1d72f7a2011-08-19 18:28:52 +100080type Extension struct {
David Symondsf511ee32012-09-06 11:36:28 +100081 // When an extension is stored in a message using SetExtension
82 // only desc and value are set. When the message is marshaled
83 // enc will be set to the encoded form of the message.
84 //
85 // When a message is unmarshaled and contains extensions, each
86 // extension will have only enc set. When such an extension is
87 // accessed using GetExtension (or GetExtensions) desc and value
88 // will be set.
David Symonds1d72f7a2011-08-19 18:28:52 +100089 desc *ExtensionDesc
90 value interface{}
91 enc []byte
92}
93
94// SetRawExtension is for testing only.
95func SetRawExtension(base extendableProto, id int32, b []byte) {
96 base.ExtensionMap()[id] = Extension{enc: b}
97}
98
David Symonds940b9612011-04-01 10:45:23 +110099// isExtensionField returns true iff the given field number is in an extension range.
100func isExtensionField(pb extendableProto, field int32) bool {
101 for _, er := range pb.ExtensionRangeArray() {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700102 if er.Start <= field && field <= er.End {
103 return true
104 }
105 }
106 return false
107}
108
David Symonds940b9612011-04-01 10:45:23 +1100109// checkExtensionTypes checks that the given extension is valid for pb.
Rob Pikea17fdd92011-11-02 12:43:05 -0700110func checkExtensionTypes(pb extendableProto, extension *ExtensionDesc) error {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700111 // Check the extended type.
Nigel Tao4ede8452011-04-28 11:27:25 +1000112 if a, b := reflect.TypeOf(pb), reflect.TypeOf(extension.ExtendedType); a != b {
David Symondsa7f3a0f2013-09-09 13:32:33 +1000113 return errors.New("proto: bad extended type; " + b.String() + " does not extend " + a.String())
Rob Pikeaaa3a622010-03-20 22:32:34 -0700114 }
115 // Check the range.
David Symonds940b9612011-04-01 10:45:23 +1100116 if !isExtensionField(pb, extension.Field) {
David Symondsa7f3a0f2013-09-09 13:32:33 +1000117 return errors.New("proto: bad extension number; not in declared ranges")
Rob Pikeaaa3a622010-03-20 22:32:34 -0700118 }
119 return nil
120}
121
David Symonds29d5d392012-12-20 12:14:58 +1100122// extPropKey is sufficient to uniquely identify an extension.
123type extPropKey struct {
124 base reflect.Type
125 field int32
126}
127
128var extProp = struct {
129 sync.RWMutex
130 m map[extPropKey]*Properties
131}{
132 m: make(map[extPropKey]*Properties),
133}
134
135func extensionProperties(ed *ExtensionDesc) *Properties {
136 key := extPropKey{base: reflect.TypeOf(ed.ExtendedType), field: ed.Field}
137
138 extProp.RLock()
139 if prop, ok := extProp.m[key]; ok {
140 extProp.RUnlock()
141 return prop
142 }
143 extProp.RUnlock()
144
145 extProp.Lock()
146 defer extProp.Unlock()
147 // Check again.
148 if prop, ok := extProp.m[key]; ok {
149 return prop
150 }
151
152 prop := new(Properties)
153 prop.Init(reflect.TypeOf(ed.ExtensionType), "unknown_name", ed.Tag, nil)
154 extProp.m[key] = prop
155 return prop
156}
157
David Symonds1d72f7a2011-08-19 18:28:52 +1000158// encodeExtensionMap encodes any unmarshaled (unencoded) extensions in m.
Rob Pikea17fdd92011-11-02 12:43:05 -0700159func encodeExtensionMap(m map[int32]Extension) error {
David Symonds1d72f7a2011-08-19 18:28:52 +1000160 for k, e := range m {
161 if e.value == nil || e.desc == nil {
162 // Extension is only in its encoded form.
163 continue
164 }
165
166 // We don't skip extensions that have an encoded form set,
167 // because the extension value may have been mutated after
168 // the last time this function was called.
169
170 et := reflect.TypeOf(e.desc.ExtensionType)
David Symonds29d5d392012-12-20 12:14:58 +1100171 props := extensionProperties(e.desc)
David Symonds1d72f7a2011-08-19 18:28:52 +1000172
173 p := NewBuffer(nil)
Russ Coxd4ce3f12012-09-12 10:36:26 +1000174 // If e.value has type T, the encoder expects a *struct{ X T }.
175 // Pass a *T with a zero field and hope it all works out.
David Symonds1d72f7a2011-08-19 18:28:52 +1000176 x := reflect.New(et)
177 x.Elem().Set(reflect.ValueOf(e.value))
Russ Coxd4ce3f12012-09-12 10:36:26 +1000178 if err := props.enc(p, props, toStructPointer(x)); err != nil {
David Symonds1d72f7a2011-08-19 18:28:52 +1000179 return err
180 }
181 e.enc = p.buf
182 m[k] = e
183 }
184 return nil
185}
186
David Symonds0bf1ad52013-10-11 09:07:50 +1100187func sizeExtensionMap(m map[int32]Extension) (n int) {
188 for _, e := range m {
189 if e.value == nil || e.desc == nil {
190 // Extension is only in its encoded form.
191 n += len(e.enc)
192 continue
193 }
194
195 // We don't skip extensions that have an encoded form set,
196 // because the extension value may have been mutated after
197 // the last time this function was called.
198
199 et := reflect.TypeOf(e.desc.ExtensionType)
200 props := extensionProperties(e.desc)
201
202 // If e.value has type T, the encoder expects a *struct{ X T }.
203 // Pass a *T with a zero field and hope it all works out.
204 x := reflect.New(et)
205 x.Elem().Set(reflect.ValueOf(e.value))
206 n += props.size(props, toStructPointer(x))
207 }
208 return
209}
210
David Symonds940b9612011-04-01 10:45:23 +1100211// HasExtension returns whether the given extension is present in pb.
212func HasExtension(pb extendableProto, extension *ExtensionDesc) bool {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700213 // TODO: Check types, field numbers, etc.?
David Symonds940b9612011-04-01 10:45:23 +1100214 _, ok := pb.ExtensionMap()[extension.Field]
Rob Pikeaaa3a622010-03-20 22:32:34 -0700215 return ok
216}
217
David Symonds940b9612011-04-01 10:45:23 +1100218// ClearExtension removes the given extension from pb.
219func ClearExtension(pb extendableProto, extension *ExtensionDesc) {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700220 // TODO: Check types, field numbers, etc.?
Rob Pikef48475f2011-10-28 12:07:40 -0700221 delete(pb.ExtensionMap(), extension.Field)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700222}
223
David Symonds940b9612011-04-01 10:45:23 +1100224// GetExtension parses and returns the given extension of pb.
David Symondsa7e9ef92012-01-18 18:27:58 +1100225// If the extension is not present it returns ErrMissingExtension.
Rob Pikea17fdd92011-11-02 12:43:05 -0700226func GetExtension(pb extendableProto, extension *ExtensionDesc) (interface{}, error) {
David Symonds940b9612011-04-01 10:45:23 +1100227 if err := checkExtensionTypes(pb, extension); err != nil {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700228 return nil, err
229 }
230
David Symondsce441e62014-11-18 13:50:03 +1100231 emap := pb.ExtensionMap()
232 e, ok := emap[extension.Field]
Rob Pikeaaa3a622010-03-20 22:32:34 -0700233 if !ok {
David Symondsa7e9ef92012-01-18 18:27:58 +1100234 return nil, ErrMissingExtension
Rob Pikeaaa3a622010-03-20 22:32:34 -0700235 }
David Symonds1d72f7a2011-08-19 18:28:52 +1000236 if e.value != nil {
237 // Already decoded. Check the descriptor, though.
238 if e.desc != extension {
239 // This shouldn't happen. If it does, it means that
240 // GetExtension was called twice with two different
241 // descriptors with the same field number.
Rob Pikea17fdd92011-11-02 12:43:05 -0700242 return nil, errors.New("proto: descriptor conflict")
David Symonds1d72f7a2011-08-19 18:28:52 +1000243 }
244 return e.value, nil
245 }
Rob Pikeaaa3a622010-03-20 22:32:34 -0700246
David Symondsa4b61c02011-09-07 14:06:00 +1000247 v, err := decodeExtension(e.enc, extension)
248 if err != nil {
249 return nil, err
250 }
251
252 // Remember the decoded version and drop the encoded version.
253 // That way it is safe to mutate what we return.
254 e.value = v
255 e.desc = extension
256 e.enc = nil
David Symondsce441e62014-11-18 13:50:03 +1100257 emap[extension.Field] = e
David Symondsa4b61c02011-09-07 14:06:00 +1000258 return e.value, nil
259}
260
261// decodeExtension decodes an extension encoded in b.
Rob Pikea17fdd92011-11-02 12:43:05 -0700262func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) {
David Symonds61826da2012-05-05 09:31:28 +1000263 o := NewBuffer(b)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700264
Nigel Tao4ede8452011-04-28 11:27:25 +1000265 t := reflect.TypeOf(extension.ExtensionType)
David Symonds61826da2012-05-05 09:31:28 +1000266 rep := extension.repeated()
267
David Symonds29d5d392012-12-20 12:14:58 +1100268 props := extensionProperties(extension)
Rob Pikeaaa3a622010-03-20 22:32:34 -0700269
David Symonds61826da2012-05-05 09:31:28 +1000270 // t is a pointer to a struct, pointer to basic type or a slice.
271 // Allocate a "field" to store the pointer/slice itself; the
272 // pointer/slice will be stored here. We pass
Rob Pikeb0447c02011-10-20 15:20:04 -0700273 // the address of this field to props.dec.
Russ Coxd4ce3f12012-09-12 10:36:26 +1000274 // This passes a zero field and a *t and lets props.dec
275 // interpret it as a *struct{ x t }.
Rob Pikeb0447c02011-10-20 15:20:04 -0700276 value := reflect.New(t).Elem()
David Symonds61826da2012-05-05 09:31:28 +1000277
278 for {
279 // Discard wire type and field number varint. It isn't needed.
280 if _, err := o.DecodeVarint(); err != nil {
281 return nil, err
282 }
283
Russ Coxd4ce3f12012-09-12 10:36:26 +1000284 if err := props.dec(o, props, toStructPointer(value.Addr())); err != nil {
David Symonds61826da2012-05-05 09:31:28 +1000285 return nil, err
286 }
287
288 if !rep || o.index >= len(o.buf) {
289 break
290 }
Rob Pikeaaa3a622010-03-20 22:32:34 -0700291 }
Rob Pikeb0447c02011-10-20 15:20:04 -0700292 return value.Interface(), nil
Rob Pikeaaa3a622010-03-20 22:32:34 -0700293}
294
David Symonds940b9612011-04-01 10:45:23 +1100295// GetExtensions returns a slice of the extensions present in pb that are also listed in es.
296// The returned slice has the same length as es; missing extensions will appear as nil elements.
David Symonds9f60f432012-06-14 09:45:25 +1000297func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, err error) {
David Symonds940b9612011-04-01 10:45:23 +1100298 epb, ok := pb.(extendableProto)
299 if !ok {
David Symondsa7f3a0f2013-09-09 13:32:33 +1000300 err = errors.New("proto: not an extendable proto")
David Symonds940b9612011-04-01 10:45:23 +1100301 return
302 }
303 extensions = make([]interface{}, len(es))
304 for i, e := range es {
305 extensions[i], err = GetExtension(epb, e)
David Symonds8b1c6b72014-06-20 14:28:56 +1000306 if err == ErrMissingExtension {
307 err = nil
308 }
David Symonds940b9612011-04-01 10:45:23 +1100309 if err != nil {
310 return
311 }
312 }
313 return
314}
315
David Symonds940b9612011-04-01 10:45:23 +1100316// SetExtension sets the specified extension of pb to the specified value.
Rob Pikea17fdd92011-11-02 12:43:05 -0700317func SetExtension(pb extendableProto, extension *ExtensionDesc, value interface{}) error {
David Symonds940b9612011-04-01 10:45:23 +1100318 if err := checkExtensionTypes(pb, extension); err != nil {
Rob Pikeaaa3a622010-03-20 22:32:34 -0700319 return err
320 }
Nigel Tao4ede8452011-04-28 11:27:25 +1000321 typ := reflect.TypeOf(extension.ExtensionType)
322 if typ != reflect.TypeOf(value) {
David Symondsa7f3a0f2013-09-09 13:32:33 +1000323 return errors.New("proto: bad extension value type")
Rob Pikeaaa3a622010-03-20 22:32:34 -0700324 }
David Symonds82b6f0b2015-03-03 06:33:00 +1100325 // nil extension values need to be caught early, because the
326 // encoder can't distinguish an ErrNil due to a nil extension
327 // from an ErrNil due to a missing field. Extensions are
328 // always optional, so the encoder would just swallow the error
329 // and drop all the extensions from the encoded message.
330 if reflect.ValueOf(value).IsNil() {
331 return fmt.Errorf("proto: SetExtension called with nil value of type %T", value)
332 }
Rob Pikeaaa3a622010-03-20 22:32:34 -0700333
David Symonds1d72f7a2011-08-19 18:28:52 +1000334 pb.ExtensionMap()[extension.Field] = Extension{desc: extension, value: value}
Rob Pikeaaa3a622010-03-20 22:32:34 -0700335 return nil
336}
David Symondse37856c2011-06-22 12:52:53 +1000337
338// A global registry of extensions.
339// The generated code will register the generated descriptors by calling RegisterExtension.
340
341var extensionMaps = make(map[reflect.Type]map[int32]*ExtensionDesc)
342
343// RegisterExtension is called from the generated code.
344func RegisterExtension(desc *ExtensionDesc) {
345 st := reflect.TypeOf(desc.ExtendedType).Elem()
346 m := extensionMaps[st]
347 if m == nil {
348 m = make(map[int32]*ExtensionDesc)
349 extensionMaps[st] = m
350 }
351 if _, ok := m[desc.Field]; ok {
352 panic("proto: duplicate extension registered: " + st.String() + " " + strconv.Itoa(int(desc.Field)))
353 }
354 m[desc.Field] = desc
355}
David Symondsc7cb3fd2011-08-29 16:49:58 +1000356
357// RegisteredExtensions returns a map of the registered extensions of a
358// protocol buffer struct, indexed by the extension number.
359// The argument pb should be a nil pointer to the struct type.
David Symonds9f60f432012-06-14 09:45:25 +1000360func RegisteredExtensions(pb Message) map[int32]*ExtensionDesc {
David Symondsc7cb3fd2011-08-29 16:49:58 +1000361 return extensionMaps[reflect.TypeOf(pb).Elem()]
362}