codec_messageset.go (3228B)
1 // Copyright 2019 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package impl 6 7 import ( 8 "sort" 9 10 "google.golang.org/protobuf/encoding/protowire" 11 "google.golang.org/protobuf/internal/encoding/messageset" 12 "google.golang.org/protobuf/internal/errors" 13 "google.golang.org/protobuf/internal/flags" 14 ) 15 16 func sizeMessageSet(mi *MessageInfo, p pointer, opts marshalOptions) (size int) { 17 if !flags.ProtoLegacy { 18 return 0 19 } 20 21 ext := *p.Apply(mi.extensionOffset).Extensions() 22 for _, x := range ext { 23 xi := getExtensionFieldInfo(x.Type()) 24 if xi.funcs.size == nil { 25 continue 26 } 27 num, _ := protowire.DecodeTag(xi.wiretag) 28 size += messageset.SizeField(num) 29 size += xi.funcs.size(x.Value(), protowire.SizeTag(messageset.FieldMessage), opts) 30 } 31 32 if u := mi.getUnknownBytes(p); u != nil { 33 size += messageset.SizeUnknown(*u) 34 } 35 36 return size 37 } 38 39 func marshalMessageSet(mi *MessageInfo, b []byte, p pointer, opts marshalOptions) ([]byte, error) { 40 if !flags.ProtoLegacy { 41 return b, errors.New("no support for message_set_wire_format") 42 } 43 44 ext := *p.Apply(mi.extensionOffset).Extensions() 45 switch len(ext) { 46 case 0: 47 case 1: 48 // Fast-path for one extension: Don't bother sorting the keys. 49 for _, x := range ext { 50 var err error 51 b, err = marshalMessageSetField(mi, b, x, opts) 52 if err != nil { 53 return b, err 54 } 55 } 56 default: 57 // Sort the keys to provide a deterministic encoding. 58 // Not sure this is required, but the old code does it. 59 keys := make([]int, 0, len(ext)) 60 for k := range ext { 61 keys = append(keys, int(k)) 62 } 63 sort.Ints(keys) 64 for _, k := range keys { 65 var err error 66 b, err = marshalMessageSetField(mi, b, ext[int32(k)], opts) 67 if err != nil { 68 return b, err 69 } 70 } 71 } 72 73 if u := mi.getUnknownBytes(p); u != nil { 74 var err error 75 b, err = messageset.AppendUnknown(b, *u) 76 if err != nil { 77 return b, err 78 } 79 } 80 81 return b, nil 82 } 83 84 func marshalMessageSetField(mi *MessageInfo, b []byte, x ExtensionField, opts marshalOptions) ([]byte, error) { 85 xi := getExtensionFieldInfo(x.Type()) 86 num, _ := protowire.DecodeTag(xi.wiretag) 87 b = messageset.AppendFieldStart(b, num) 88 b, err := xi.funcs.marshal(b, x.Value(), protowire.EncodeTag(messageset.FieldMessage, protowire.BytesType), opts) 89 if err != nil { 90 return b, err 91 } 92 b = messageset.AppendFieldEnd(b) 93 return b, nil 94 } 95 96 func unmarshalMessageSet(mi *MessageInfo, b []byte, p pointer, opts unmarshalOptions) (out unmarshalOutput, err error) { 97 if !flags.ProtoLegacy { 98 return out, errors.New("no support for message_set_wire_format") 99 } 100 101 ep := p.Apply(mi.extensionOffset).Extensions() 102 if *ep == nil { 103 *ep = make(map[int32]ExtensionField) 104 } 105 ext := *ep 106 initialized := true 107 err = messageset.Unmarshal(b, true, func(num protowire.Number, v []byte) error { 108 o, err := mi.unmarshalExtension(v, num, protowire.BytesType, ext, opts) 109 if err == errUnknown { 110 u := mi.mutableUnknownBytes(p) 111 *u = protowire.AppendTag(*u, num, protowire.BytesType) 112 *u = append(*u, v...) 113 return nil 114 } 115 if !o.initialized { 116 initialized = false 117 } 118 return err 119 }) 120 out.n = len(b) 121 out.initialized = initialized 122 return out, err 123 }