1 // Go support for Protocol Buffers - Google's data interchange format
3 // Copyright 2010 Google Inc. All rights reserved.
4 // http://code.google.com/p/goprotobuf/
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are
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
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.
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.
35 * Support for message sets.
44 // ErrNoMessageTypeId occurs when a protocol buffer does not have a message type ID.
45 // A message type ID is required for storing a protocol buffer in a message set.
46 var ErrNoMessageTypeId = os.NewError("proto does not have a message type ID")
48 // The first two types (_MessageSet_Item and MessageSet)
49 // model what the protocol compiler produces for the following protocol message:
50 // message MessageSet {
51 // repeated group Item = 1 {
52 // required int32 type_id = 2;
53 // required string message = 3;
56 // That is the MessageSet wire format. We can't use a proto to generate these
57 // because that would introduce a circular dependency between it and this package.
59 // When a proto1 proto has a field that looks like:
60 // optional message<MessageSet> info = 3;
61 // the protocol compiler produces a field in the generated struct that looks like:
62 // Info *_proto_.MessageSet `protobuf:"bytes,3,opt,name=info"`
63 // The package is automatically inserted so there is no need for that proto file to
64 // import this package.
66 type _MessageSet_Item struct {
67 TypeId *int32 `protobuf:"varint,2,req,name=type_id"`
68 Message []byte `protobuf:"bytes,3,req,name=message"`
71 type MessageSet struct {
72 Item []*_MessageSet_Item `protobuf:"group,1,rep"`
73 XXX_unrecognized *bytes.Buffer
77 // messageTypeIder is an interface satisfied by a protocol buffer type
78 // that may be stored in a MessageSet.
79 type messageTypeIder interface {
83 func (ms *MessageSet) find(pb interface{}) *_MessageSet_Item {
84 mti, ok := pb.(messageTypeIder)
88 id := mti.MessageTypeId()
89 for _, item := range ms.Item {
90 if *item.TypeId == id {
97 func (ms *MessageSet) Has(pb interface{}) bool {
98 if ms.find(pb) != nil {
104 func (ms *MessageSet) Unmarshal(pb interface{}) os.Error {
105 if item := ms.find(pb); item != nil {
106 return Unmarshal(item.Message, pb)
108 if _, ok := pb.(messageTypeIder); !ok {
109 return ErrNoMessageTypeId
111 return nil // TODO: return error instead?
114 func (ms *MessageSet) Marshal(pb interface{}) os.Error {
115 msg, err := Marshal(pb)
119 if item := ms.find(pb); item != nil {
120 // reuse existing item
125 mti, ok := pb.(messageTypeIder)
127 return ErrWrongType // TODO: custom error?
130 mtid := mti.MessageTypeId()
131 ms.Item = append(ms.Item, &_MessageSet_Item{
138 // Support for the message_set_wire_format message option.
140 func skipVarint(buf []byte) []byte {
142 for ; buf[i]&0x80 != 0; i++ {
147 // MarshalMessageSet encodes the extension map represented by m in the message set wire format.
148 // It is called by generated Marshal methods on protocol buffer messages with the message_set_wire_format option.
149 func MarshalMessageSet(m map[int32]Extension) ([]byte, os.Error) {
150 if err := encodeExtensionMap(m); err != nil {
154 ms := &MessageSet{Item: make([]*_MessageSet_Item, len(m))}
156 for k, e := range m {
157 // Remove the wire type and field number varint, as well as the length varint.
158 msg := skipVarint(skipVarint(e.enc))
160 ms.Item[i] = &_MessageSet_Item{
169 // UnmarshalMessageSet decodes the extension map encoded in buf in the message set wire format.
170 // It is called by generated Unmarshal methods on protocol buffer messages with the message_set_wire_format option.
171 func UnmarshalMessageSet(buf []byte, m map[int32]Extension) os.Error {
172 ms := new(MessageSet)
173 if err := Unmarshal(buf, ms); err != nil {
176 for _, item := range ms.Item {
177 // restore wire type and field number varint, plus length varint.
178 b := EncodeVarint(uint64(*item.TypeId)<<3 | WireBytes)
179 b = append(b, EncodeVarint(uint64(len(item.Message)))...)
180 b = append(b, item.Message...)
182 m[*item.TypeId] = Extension{enc: b}
187 // A global registry of types that can be used in a MessageSet.
189 var messageSetMap = make(map[int32]messageSetDesc)
191 type messageSetDesc struct {
192 t reflect.Type // pointer to struct
196 // RegisterMessageSetType is called from the generated code.
197 func RegisterMessageSetType(i messageTypeIder, name string) {
198 messageSetMap[i.MessageTypeId()] = messageSetDesc{
199 t: reflect.TypeOf(i),