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 "errors" 40 ) 41 42 // errNoMessageTypeID occurs when a protocol buffer does not have a message type ID. 43 // A message type ID is required for storing a protocol buffer in a message set. 44 var errNoMessageTypeID = errors.New("proto does not have a message type ID") 45 46 // The first two types (_MessageSet_Item and messageSet) 47 // model what the protocol compiler produces for the following protocol message: 48 // message MessageSet { 49 // repeated group Item = 1 { 50 // required int32 type_id = 2; 51 // required string message = 3; 52 // }; 53 // } 54 // That is the MessageSet wire format. We can't use a proto to generate these 55 // because that would introduce a circular dependency between it and this package. 56 57 type _MessageSet_Item struct { 58 TypeId *int32 `protobuf:"varint,2,req,name=type_id"` 59 Message []byte `protobuf:"bytes,3,req,name=message"` 60 } 61 62 type messageSet struct { 63 Item []*_MessageSet_Item `protobuf:"group,1,rep"` 64 XXX_unrecognized []byte 65 // TODO: caching? 66 } 67 68 // Make sure messageSet is a Message. 69 var _ Message = (*messageSet)(nil) 70 71 // messageTypeIder is an interface satisfied by a protocol buffer type 72 // that may be stored in a MessageSet. 73 type messageTypeIder interface { 74 MessageTypeId() int32 75 } 76 77 func (ms *messageSet) find(pb Message) *_MessageSet_Item { 78 mti, ok := pb.(messageTypeIder) 79 if !ok { 80 return nil 81 } 82 id := mti.MessageTypeId() 83 for _, item := range ms.Item { 84 if *item.TypeId == id { 85 return item 86 } 87 } 88 return nil 89 } 90 91 func (ms *messageSet) Has(pb Message) bool { 92 return ms.find(pb) != nil 93 } 94 95 func (ms *messageSet) Unmarshal(pb Message) error { 96 if item := ms.find(pb); item != nil { 97 return Unmarshal(item.Message, pb) 98 } 99 if _, ok := pb.(messageTypeIder); !ok { 100 return errNoMessageTypeID 101 } 102 return nil // TODO: return error instead? 103 } 104 105 func (ms *messageSet) Marshal(pb Message) error { 106 msg, err := Marshal(pb) 107 if err != nil { 108 return err 109 } 110 if item := ms.find(pb); item != nil { 111 // reuse existing item 112 item.Message = msg 113 return nil 114 } 115 116 mti, ok := pb.(messageTypeIder) 117 if !ok { 118 return errNoMessageTypeID 119 } 120 121 mtid := mti.MessageTypeId() 122 ms.Item = append(ms.Item, &_MessageSet_Item{ 123 TypeId: &mtid, 124 Message: msg, 125 }) 126 return nil 127 } 128 129 func (ms *messageSet) Reset() { *ms = messageSet{} } 130 func (ms *messageSet) String() string { return CompactTextString(ms) } 131 func (*messageSet) ProtoMessage() {} 132 133 // Support for the message_set_wire_format message option. 134 135 func skipVarint(buf []byte) []byte { 136 i := 0 137 for ; buf[i]&0x80 != 0; i++ { 138 } 139 return buf[i+1:] 140 } 141 142 // unmarshalMessageSet decodes the extension map encoded in buf in the message set wire format. 143 // It is called by Unmarshal methods on protocol buffer messages with the message_set_wire_format option. 144 func unmarshalMessageSet(buf []byte, exts interface{}) error { 145 var m map[int32]Extension 146 switch exts := exts.(type) { 147 case *XXX_InternalExtensions: 148 m = exts.extensionsWrite() 149 case map[int32]Extension: 150 m = exts 151 default: 152 return errors.New("proto: not an extension map") 153 } 154 155 ms := new(messageSet) 156 if err := Unmarshal(buf, ms); err != nil { 157 return err 158 } 159 for _, item := range ms.Item { 160 id := *item.TypeId 161 msg := item.Message 162 163 // Restore wire type and field number varint, plus length varint. 164 // Be careful to preserve duplicate items. 165 b := EncodeVarint(uint64(id)<<3 | WireBytes) 166 if ext, ok := m[id]; ok { 167 // Existing data; rip off the tag and length varint 168 // so we join the new data correctly. 169 // We can assume that ext.enc is set because we are unmarshaling. 170 o := ext.enc[len(b):] // skip wire type and field number 171 _, n := DecodeVarint(o) // calculate length of length varint 172 o = o[n:] // skip length varint 173 msg = append(o, msg...) // join old data and new data 174 } 175 b = append(b, EncodeVarint(uint64(len(msg)))...) 176 b = append(b, msg...) 177 178 m[id] = Extension{enc: b} 179 } 180 return nil 181 } 182