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 } 312