OSDN Git Service

new repo
[bytom/vapor.git] / vendor / github.com / golang / protobuf / proto / message_set.go
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
32 package proto
33
34 /*
35  * Support for message sets.
36  */
37
38 import (
39         "bytes"
40         "encoding/json"
41         "errors"
42         "fmt"
43         "reflect"
44         "sort"
45 )
46
47 // errNoMessageTypeID occurs when a protocol buffer does not have a message type ID.
48 // A message type ID is required for storing a protocol buffer in a message set.
49 var errNoMessageTypeID = errors.New("proto does not have a message type ID")
50
51 // The first two types (_MessageSet_Item and messageSet)
52 // model what the protocol compiler produces for the following protocol message:
53 //   message MessageSet {
54 //     repeated group Item = 1 {
55 //       required int32 type_id = 2;
56 //       required string message = 3;
57 //     };
58 //   }
59 // That is the MessageSet wire format. We can't use a proto to generate these
60 // because that would introduce a circular dependency between it and this package.
61
62 type _MessageSet_Item struct {
63         TypeId  *int32 `protobuf:"varint,2,req,name=type_id"`
64         Message []byte `protobuf:"bytes,3,req,name=message"`
65 }
66
67 type messageSet struct {
68         Item             []*_MessageSet_Item `protobuf:"group,1,rep"`
69         XXX_unrecognized []byte
70         // TODO: caching?
71 }
72
73 // Make sure messageSet is a Message.
74 var _ Message = (*messageSet)(nil)
75
76 // messageTypeIder is an interface satisfied by a protocol buffer type
77 // that may be stored in a MessageSet.
78 type messageTypeIder interface {
79         MessageTypeId() int32
80 }
81
82 func (ms *messageSet) find(pb Message) *_MessageSet_Item {
83         mti, ok := pb.(messageTypeIder)
84         if !ok {
85                 return nil
86         }
87         id := mti.MessageTypeId()
88         for _, item := range ms.Item {
89                 if *item.TypeId == id {
90                         return item
91                 }
92         }
93         return nil
94 }
95
96 func (ms *messageSet) Has(pb Message) bool {
97         if ms.find(pb) != nil {
98                 return true
99         }
100         return false
101 }
102
103 func (ms *messageSet) Unmarshal(pb Message) error {
104         if item := ms.find(pb); item != nil {
105                 return Unmarshal(item.Message, pb)
106         }
107         if _, ok := pb.(messageTypeIder); !ok {
108                 return errNoMessageTypeID
109         }
110         return nil // TODO: return error instead?
111 }
112
113 func (ms *messageSet) Marshal(pb Message) error {
114         msg, err := Marshal(pb)
115         if err != nil {
116                 return err
117         }
118         if item := ms.find(pb); item != nil {
119                 // reuse existing item
120                 item.Message = msg
121                 return nil
122         }
123
124         mti, ok := pb.(messageTypeIder)
125         if !ok {
126                 return errNoMessageTypeID
127         }
128
129         mtid := mti.MessageTypeId()
130         ms.Item = append(ms.Item, &_MessageSet_Item{
131                 TypeId:  &mtid,
132                 Message: msg,
133         })
134         return nil
135 }
136
137 func (ms *messageSet) Reset()         { *ms = messageSet{} }
138 func (ms *messageSet) String() string { return CompactTextString(ms) }
139 func (*messageSet) ProtoMessage()     {}
140
141 // Support for the message_set_wire_format message option.
142
143 func skipVarint(buf []byte) []byte {
144         i := 0
145         for ; buf[i]&0x80 != 0; i++ {
146         }
147         return buf[i+1:]
148 }
149
150 // MarshalMessageSet encodes the extension map represented by m in the message set wire format.
151 // It is called by generated Marshal methods on protocol buffer messages with the message_set_wire_format option.
152 func MarshalMessageSet(exts interface{}) ([]byte, error) {
153         var m map[int32]Extension
154         switch exts := exts.(type) {
155         case *XXX_InternalExtensions:
156                 if err := encodeExtensions(exts); err != nil {
157                         return nil, err
158                 }
159                 m, _ = exts.extensionsRead()
160         case map[int32]Extension:
161                 if err := encodeExtensionsMap(exts); err != nil {
162                         return nil, err
163                 }
164                 m = exts
165         default:
166                 return nil, errors.New("proto: not an extension map")
167         }
168
169         // Sort extension IDs to provide a deterministic encoding.
170         // See also enc_map in encode.go.
171         ids := make([]int, 0, len(m))
172         for id := range m {
173                 ids = append(ids, int(id))
174         }
175         sort.Ints(ids)
176
177         ms := &messageSet{Item: make([]*_MessageSet_Item, 0, len(m))}
178         for _, id := range ids {
179                 e := m[int32(id)]
180                 // Remove the wire type and field number varint, as well as the length varint.
181                 msg := skipVarint(skipVarint(e.enc))
182
183                 ms.Item = append(ms.Item, &_MessageSet_Item{
184                         TypeId:  Int32(int32(id)),
185                         Message: msg,
186                 })
187         }
188         return Marshal(ms)
189 }
190
191 // UnmarshalMessageSet decodes the extension map encoded in buf in the message set wire format.
192 // It is called by generated Unmarshal methods on protocol buffer messages with the message_set_wire_format option.
193 func UnmarshalMessageSet(buf []byte, exts interface{}) error {
194         var m map[int32]Extension
195         switch exts := exts.(type) {
196         case *XXX_InternalExtensions:
197                 m = exts.extensionsWrite()
198         case map[int32]Extension:
199                 m = exts
200         default:
201                 return errors.New("proto: not an extension map")
202         }
203
204         ms := new(messageSet)
205         if err := Unmarshal(buf, ms); err != nil {
206                 return err
207         }
208         for _, item := range ms.Item {
209                 id := *item.TypeId
210                 msg := item.Message
211
212                 // Restore wire type and field number varint, plus length varint.
213                 // Be careful to preserve duplicate items.
214                 b := EncodeVarint(uint64(id)<<3 | WireBytes)
215                 if ext, ok := m[id]; ok {
216                         // Existing data; rip off the tag and length varint
217                         // so we join the new data correctly.
218                         // We can assume that ext.enc is set because we are unmarshaling.
219                         o := ext.enc[len(b):]   // skip wire type and field number
220                         _, n := DecodeVarint(o) // calculate length of length varint
221                         o = o[n:]               // skip length varint
222                         msg = append(o, msg...) // join old data and new data
223                 }
224                 b = append(b, EncodeVarint(uint64(len(msg)))...)
225                 b = append(b, msg...)
226
227                 m[id] = Extension{enc: b}
228         }
229         return nil
230 }
231
232 // MarshalMessageSetJSON encodes the extension map represented by m in JSON format.
233 // It is called by generated MarshalJSON methods on protocol buffer messages with the message_set_wire_format option.
234 func MarshalMessageSetJSON(exts interface{}) ([]byte, error) {
235         var m map[int32]Extension
236         switch exts := exts.(type) {
237         case *XXX_InternalExtensions:
238                 m, _ = exts.extensionsRead()
239         case map[int32]Extension:
240                 m = exts
241         default:
242                 return nil, errors.New("proto: not an extension map")
243         }
244         var b bytes.Buffer
245         b.WriteByte('{')
246
247         // Process the map in key order for deterministic output.
248         ids := make([]int32, 0, len(m))
249         for id := range m {
250                 ids = append(ids, id)
251         }
252         sort.Sort(int32Slice(ids)) // int32Slice defined in text.go
253
254         for i, id := range ids {
255                 ext := m[id]
256                 if i > 0 {
257                         b.WriteByte(',')
258                 }
259
260                 msd, ok := messageSetMap[id]
261                 if !ok {
262                         // Unknown type; we can't render it, so skip it.
263                         continue
264                 }
265                 fmt.Fprintf(&b, `"[%s]":`, msd.name)
266
267                 x := ext.value
268                 if x == nil {
269                         x = reflect.New(msd.t.Elem()).Interface()
270                         if err := Unmarshal(ext.enc, x.(Message)); err != nil {
271                                 return nil, err
272                         }
273                 }
274                 d, err := json.Marshal(x)
275                 if err != nil {
276                         return nil, err
277                 }
278                 b.Write(d)
279         }
280         b.WriteByte('}')
281         return b.Bytes(), nil
282 }
283
284 // UnmarshalMessageSetJSON decodes the extension map encoded in buf in JSON format.
285 // It is called by generated UnmarshalJSON methods on protocol buffer messages with the message_set_wire_format option.
286 func UnmarshalMessageSetJSON(buf []byte, exts interface{}) error {
287         // Common-case fast path.
288         if len(buf) == 0 || bytes.Equal(buf, []byte("{}")) {
289                 return nil
290         }
291
292         // This is fairly tricky, and it's not clear that it is needed.
293         return errors.New("TODO: UnmarshalMessageSetJSON not yet implemented")
294 }
295
296 // A global registry of types that can be used in a MessageSet.
297
298 var messageSetMap = make(map[int32]messageSetDesc)
299
300 type messageSetDesc struct {
301         t    reflect.Type // pointer to struct
302         name string
303 }
304
305 // RegisterMessageSetType is called from the generated code.
306 func RegisterMessageSetType(m Message, fieldNum int32, name string) {
307         messageSetMap[fieldNum] = messageSetDesc{
308                 t:    reflect.TypeOf(m),
309                 name: name,
310         }
311 }