vendor/github.com/golang/protobuf/proto/message_set.go
changeset 251 1c52a0eeb952
parent 242 2a9ec03fe5a1
equal deleted inserted replaced
250:c040f992052f 251:1c52a0eeb952
    34 /*
    34 /*
    35  * Support for message sets.
    35  * Support for message sets.
    36  */
    36  */
    37 
    37 
    38 import (
    38 import (
    39 	"bytes"
       
    40 	"encoding/json"
       
    41 	"errors"
    39 	"errors"
    42 	"fmt"
       
    43 	"reflect"
       
    44 	"sort"
       
    45 	"sync"
       
    46 )
    40 )
    47 
    41 
    48 // errNoMessageTypeID occurs when a protocol buffer does not have a message type ID.
    42 // errNoMessageTypeID occurs when a protocol buffer does not have a message type ID.
    49 // A message type ID is required for storing a protocol buffer in a message set.
    43 // A message type ID is required for storing a protocol buffer in a message set.
    50 var errNoMessageTypeID = errors.New("proto does not have a message type ID")
    44 var errNoMessageTypeID = errors.New("proto does not have a message type ID")
   143 	for ; buf[i]&0x80 != 0; i++ {
   137 	for ; buf[i]&0x80 != 0; i++ {
   144 	}
   138 	}
   145 	return buf[i+1:]
   139 	return buf[i+1:]
   146 }
   140 }
   147 
   141 
   148 // MarshalMessageSet encodes the extension map represented by m in the message set wire format.
   142 // unmarshalMessageSet decodes the extension map encoded in buf in the message set wire format.
   149 // It is called by generated Marshal methods on protocol buffer messages with the message_set_wire_format option.
       
   150 func MarshalMessageSet(exts interface{}) ([]byte, error) {
       
   151 	return marshalMessageSet(exts, false)
       
   152 }
       
   153 
       
   154 // marshaMessageSet implements above function, with the opt to turn on / off deterministic during Marshal.
       
   155 func marshalMessageSet(exts interface{}, deterministic bool) ([]byte, error) {
       
   156 	switch exts := exts.(type) {
       
   157 	case *XXX_InternalExtensions:
       
   158 		var u marshalInfo
       
   159 		siz := u.sizeMessageSet(exts)
       
   160 		b := make([]byte, 0, siz)
       
   161 		return u.appendMessageSet(b, exts, deterministic)
       
   162 
       
   163 	case map[int32]Extension:
       
   164 		// This is an old-style extension map.
       
   165 		// Wrap it in a new-style XXX_InternalExtensions.
       
   166 		ie := XXX_InternalExtensions{
       
   167 			p: &struct {
       
   168 				mu           sync.Mutex
       
   169 				extensionMap map[int32]Extension
       
   170 			}{
       
   171 				extensionMap: exts,
       
   172 			},
       
   173 		}
       
   174 
       
   175 		var u marshalInfo
       
   176 		siz := u.sizeMessageSet(&ie)
       
   177 		b := make([]byte, 0, siz)
       
   178 		return u.appendMessageSet(b, &ie, deterministic)
       
   179 
       
   180 	default:
       
   181 		return nil, errors.New("proto: not an extension map")
       
   182 	}
       
   183 }
       
   184 
       
   185 // UnmarshalMessageSet decodes the extension map encoded in buf in the message set wire format.
       
   186 // It is called by Unmarshal methods on protocol buffer messages with the message_set_wire_format option.
   143 // It is called by Unmarshal methods on protocol buffer messages with the message_set_wire_format option.
   187 func UnmarshalMessageSet(buf []byte, exts interface{}) error {
   144 func unmarshalMessageSet(buf []byte, exts interface{}) error {
   188 	var m map[int32]Extension
   145 	var m map[int32]Extension
   189 	switch exts := exts.(type) {
   146 	switch exts := exts.(type) {
   190 	case *XXX_InternalExtensions:
   147 	case *XXX_InternalExtensions:
   191 		m = exts.extensionsWrite()
   148 		m = exts.extensionsWrite()
   192 	case map[int32]Extension:
   149 	case map[int32]Extension:
   220 
   177 
   221 		m[id] = Extension{enc: b}
   178 		m[id] = Extension{enc: b}
   222 	}
   179 	}
   223 	return nil
   180 	return nil
   224 }
   181 }
   225 
       
   226 // MarshalMessageSetJSON encodes the extension map represented by m in JSON format.
       
   227 // It is called by generated MarshalJSON methods on protocol buffer messages with the message_set_wire_format option.
       
   228 func MarshalMessageSetJSON(exts interface{}) ([]byte, error) {
       
   229 	var m map[int32]Extension
       
   230 	switch exts := exts.(type) {
       
   231 	case *XXX_InternalExtensions:
       
   232 		var mu sync.Locker
       
   233 		m, mu = exts.extensionsRead()
       
   234 		if m != nil {
       
   235 			// Keep the extensions map locked until we're done marshaling to prevent
       
   236 			// races between marshaling and unmarshaling the lazily-{en,de}coded
       
   237 			// values.
       
   238 			mu.Lock()
       
   239 			defer mu.Unlock()
       
   240 		}
       
   241 	case map[int32]Extension:
       
   242 		m = exts
       
   243 	default:
       
   244 		return nil, errors.New("proto: not an extension map")
       
   245 	}
       
   246 	var b bytes.Buffer
       
   247 	b.WriteByte('{')
       
   248 
       
   249 	// Process the map in key order for deterministic output.
       
   250 	ids := make([]int32, 0, len(m))
       
   251 	for id := range m {
       
   252 		ids = append(ids, id)
       
   253 	}
       
   254 	sort.Sort(int32Slice(ids)) // int32Slice defined in text.go
       
   255 
       
   256 	for i, id := range ids {
       
   257 		ext := m[id]
       
   258 		msd, ok := messageSetMap[id]
       
   259 		if !ok {
       
   260 			// Unknown type; we can't render it, so skip it.
       
   261 			continue
       
   262 		}
       
   263 
       
   264 		if i > 0 && b.Len() > 1 {
       
   265 			b.WriteByte(',')
       
   266 		}
       
   267 
       
   268 		fmt.Fprintf(&b, `"[%s]":`, msd.name)
       
   269 
       
   270 		x := ext.value
       
   271 		if x == nil {
       
   272 			x = reflect.New(msd.t.Elem()).Interface()
       
   273 			if err := Unmarshal(ext.enc, x.(Message)); err != nil {
       
   274 				return nil, err
       
   275 			}
       
   276 		}
       
   277 		d, err := json.Marshal(x)
       
   278 		if err != nil {
       
   279 			return nil, err
       
   280 		}
       
   281 		b.Write(d)
       
   282 	}
       
   283 	b.WriteByte('}')
       
   284 	return b.Bytes(), nil
       
   285 }
       
   286 
       
   287 // UnmarshalMessageSetJSON decodes the extension map encoded in buf in JSON format.
       
   288 // It is called by generated UnmarshalJSON methods on protocol buffer messages with the message_set_wire_format option.
       
   289 func UnmarshalMessageSetJSON(buf []byte, exts interface{}) error {
       
   290 	// Common-case fast path.
       
   291 	if len(buf) == 0 || bytes.Equal(buf, []byte("{}")) {
       
   292 		return nil
       
   293 	}
       
   294 
       
   295 	// This is fairly tricky, and it's not clear that it is needed.
       
   296 	return errors.New("TODO: UnmarshalMessageSetJSON not yet implemented")
       
   297 }
       
   298 
       
   299 // A global registry of types that can be used in a MessageSet.
       
   300 
       
   301 var messageSetMap = make(map[int32]messageSetDesc)
       
   302 
       
   303 type messageSetDesc struct {
       
   304 	t    reflect.Type // pointer to struct
       
   305 	name string
       
   306 }
       
   307 
       
   308 // RegisterMessageSetType is called from the generated code.
       
   309 func RegisterMessageSetType(m Message, fieldNum int32, name string) {
       
   310 	messageSetMap[fieldNum] = messageSetDesc{
       
   311 		t:    reflect.TypeOf(m),
       
   312 		name: name,
       
   313 	}
       
   314 }