github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/golang/protobuf/proto/message_set.go (about) 1 // Go support for Protocol Buffers - Google's data interchange format 2 // 3 // Copyright 2010 The Go Authors. All rights reserved. 4 // https://yougam/libraries/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(m map[int32]Extension) ([]byte, error) { 153 if err := encodeExtensionMap(m); err != nil { 154 return nil, err 155 } 156 157 // Sort extension IDs to provide a deterministic encoding. 158 // See also enc_map in encode.go. 159 ids := make([]int, 0, len(m)) 160 for id := range m { 161 ids = append(ids, int(id)) 162 } 163 sort.Ints(ids) 164 165 ms := &messageSet{Item: make([]*_MessageSet_Item, 0, len(m))} 166 for _, id := range ids { 167 e := m[int32(id)] 168 // Remove the wire type and field number varint, as well as the length varint. 169 msg := skipVarint(skipVarint(e.enc)) 170 171 ms.Item = append(ms.Item, &_MessageSet_Item{ 172 TypeId: Int32(int32(id)), 173 Message: msg, 174 }) 175 } 176 return Marshal(ms) 177 } 178 179 // UnmarshalMessageSet decodes the extension map encoded in buf in the message set wire format. 180 // It is called by generated Unmarshal methods on protocol buffer messages with the message_set_wire_format option. 181 func UnmarshalMessageSet(buf []byte, m map[int32]Extension) error { 182 ms := new(messageSet) 183 if err := Unmarshal(buf, ms); err != nil { 184 return err 185 } 186 for _, item := range ms.Item { 187 id := *item.TypeId 188 msg := item.Message 189 190 // Restore wire type and field number varint, plus length varint. 191 // Be careful to preserve duplicate items. 192 b := EncodeVarint(uint64(id)<<3 | WireBytes) 193 if ext, ok := m[id]; ok { 194 // Existing data; rip off the tag and length varint 195 // so we join the new data correctly. 196 // We can assume that ext.enc is set because we are unmarshaling. 197 o := ext.enc[len(b):] // skip wire type and field number 198 _, n := DecodeVarint(o) // calculate length of length varint 199 o = o[n:] // skip length varint 200 msg = append(o, msg...) // join old data and new data 201 } 202 b = append(b, EncodeVarint(uint64(len(msg)))...) 203 b = append(b, msg...) 204 205 m[id] = Extension{enc: b} 206 } 207 return nil 208 } 209 210 // MarshalMessageSetJSON encodes the extension map represented by m in JSON format. 211 // It is called by generated MarshalJSON methods on protocol buffer messages with the message_set_wire_format option. 212 func MarshalMessageSetJSON(m map[int32]Extension) ([]byte, error) { 213 var b bytes.Buffer 214 b.WriteByte('{') 215 216 // Process the map in key order for deterministic output. 217 ids := make([]int32, 0, len(m)) 218 for id := range m { 219 ids = append(ids, id) 220 } 221 sort.Sort(int32Slice(ids)) // int32Slice defined in text.go 222 223 for i, id := range ids { 224 ext := m[id] 225 if i > 0 { 226 b.WriteByte(',') 227 } 228 229 msd, ok := messageSetMap[id] 230 if !ok { 231 // Unknown type; we can't render it, so skip it. 232 continue 233 } 234 fmt.Fprintf(&b, `"[%s]":`, msd.name) 235 236 x := ext.value 237 if x == nil { 238 x = reflect.New(msd.t.Elem()).Interface() 239 if err := Unmarshal(ext.enc, x.(Message)); err != nil { 240 return nil, err 241 } 242 } 243 d, err := json.Marshal(x) 244 if err != nil { 245 return nil, err 246 } 247 b.Write(d) 248 } 249 b.WriteByte('}') 250 return b.Bytes(), nil 251 } 252 253 // UnmarshalMessageSetJSON decodes the extension map encoded in buf in JSON format. 254 // It is called by generated UnmarshalJSON methods on protocol buffer messages with the message_set_wire_format option. 255 func UnmarshalMessageSetJSON(buf []byte, m map[int32]Extension) error { 256 // Common-case fast path. 257 if len(buf) == 0 || bytes.Equal(buf, []byte("{}")) { 258 return nil 259 } 260 261 // This is fairly tricky, and it's not clear that it is needed. 262 return errors.New("TODO: UnmarshalMessageSetJSON not yet implemented") 263 } 264 265 // A global registry of types that can be used in a MessageSet. 266 267 var messageSetMap = make(map[int32]messageSetDesc) 268 269 type messageSetDesc struct { 270 t reflect.Type // pointer to struct 271 name string 272 } 273 274 // RegisterMessageSetType is called from the generated code. 275 func RegisterMessageSetType(m Message, fieldNum int32, name string) { 276 messageSetMap[fieldNum] = messageSetDesc{ 277 t: reflect.TypeOf(m), 278 name: name, 279 } 280 }