diff options
Diffstat (limited to 'proto/message_set.go')
-rw-r--r-- | proto/message_set.go | 64 |
1 files changed, 61 insertions, 3 deletions
diff --git a/proto/message_set.go b/proto/message_set.go index 1a17809..5504855 100644 --- a/proto/message_set.go +++ b/proto/message_set.go @@ -36,7 +36,10 @@ package proto */ import ( + "bytes" + "encoding/json" "errors" + "fmt" "reflect" "sort" ) @@ -211,6 +214,61 @@ func UnmarshalMessageSet(buf []byte, m map[int32]Extension) error { return nil } +// MarshalMessageSetJSON encodes the extension map represented by m in JSON format. +// It is called by generated MarshalJSON methods on protocol buffer messages with the message_set_wire_format option. +func MarshalMessageSetJSON(m map[int32]Extension) ([]byte, error) { + var b bytes.Buffer + b.WriteByte('{') + + // Process the map in key order for deterministic output. + ids := make([]int32, 0, len(m)) + for id := range m { + ids = append(ids, id) + } + sort.Sort(int32Slice(ids)) // int32Slice defined in text.go + + for i, id := range ids { + ext := m[id] + if i > 0 { + b.WriteByte(',') + } + + msd, ok := messageSetMap[id] + if !ok { + // Unknown type; we can't render it, so skip it. + continue + } + fmt.Fprintf(&b, `"[%s]":`, msd.name) + + x := ext.value + if x == nil { + x = reflect.New(msd.t.Elem()).Interface() + if err := Unmarshal(ext.enc, x.(Message)); err != nil { + return nil, err + } + } + d, err := json.Marshal(x) + if err != nil { + return nil, err + } + b.Write(d) + } + b.WriteByte('}') + return b.Bytes(), nil +} + +// UnmarshalMessageSetJSON decodes the extension map encoded in buf in JSON format. +// It is called by generated UnmarshalJSON methods on protocol buffer messages with the message_set_wire_format option. +func UnmarshalMessageSetJSON(buf []byte, m map[int32]Extension) error { + // Common-case fast path. + if len(buf) == 0 || bytes.Equal(buf, []byte("{}")) { + return nil + } + + // This is fairly tricky, and it's not clear that it is needed. + return errors.New("TODO: UnmarshalMessageSetJSON not yet implemented") +} + // A global registry of types that can be used in a MessageSet. var messageSetMap = make(map[int32]messageSetDesc) @@ -221,9 +279,9 @@ type messageSetDesc struct { } // RegisterMessageSetType is called from the generated code. -func RegisterMessageSetType(i messageTypeIder, name string) { - messageSetMap[i.MessageTypeId()] = messageSetDesc{ - t: reflect.TypeOf(i), +func RegisterMessageSetType(m Message, fieldNum int32, name string) { + messageSetMap[fieldNum] = messageSetDesc{ + t: reflect.TypeOf(m), name: name, } } |