Home | History | Annotate | Download | only in proto
      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