blob: e27e0b7d54554261e8768f32e7e613a1d481bd51 [file] [log] [blame]
Damien Neil302cb322019-06-19 15:22:13 -07001// 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
5package proto
6
7import (
8 "google.golang.org/protobuf/internal/encoding/messageset"
9 "google.golang.org/protobuf/internal/encoding/wire"
10 "google.golang.org/protobuf/internal/errors"
11 "google.golang.org/protobuf/internal/flags"
12 "google.golang.org/protobuf/reflect/protoreflect"
13 "google.golang.org/protobuf/reflect/protoregistry"
14)
15
16func sizeMessageSet(m protoreflect.Message) (size int) {
17 m.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
18 size += messageset.SizeField(fd.Number())
19 size += wire.SizeTag(messageset.FieldMessage)
20 size += wire.SizeBytes(sizeMessage(v.Message()))
21 return true
22 })
Damien Neilce3384c2019-11-06 13:18:28 -080023 size += messageset.SizeUnknown(m.GetUnknown())
Damien Neil302cb322019-06-19 15:22:13 -070024 return size
25}
26
27func marshalMessageSet(b []byte, m protoreflect.Message, o MarshalOptions) ([]byte, error) {
Joe Tsai1799d112019-08-08 13:31:59 -070028 if !flags.ProtoLegacy {
Damien Neil302cb322019-06-19 15:22:13 -070029 return b, errors.New("no support for message_set_wire_format")
30 }
31 var err error
32 o.rangeFields(m, func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
33 b, err = marshalMessageSetField(b, fd, v, o)
34 return err == nil
35 })
36 if err != nil {
37 return b, err
38 }
Damien Neilce3384c2019-11-06 13:18:28 -080039 return messageset.AppendUnknown(b, m.GetUnknown())
Damien Neil302cb322019-06-19 15:22:13 -070040}
41
42func marshalMessageSetField(b []byte, fd protoreflect.FieldDescriptor, value protoreflect.Value, o MarshalOptions) ([]byte, error) {
43 b = messageset.AppendFieldStart(b, fd.Number())
44 b = wire.AppendTag(b, messageset.FieldMessage, wire.BytesType)
45 b = wire.AppendVarint(b, uint64(o.Size(value.Message().Interface())))
46 b, err := o.marshalMessage(b, value.Message())
47 if err != nil {
48 return b, err
49 }
50 b = messageset.AppendFieldEnd(b)
51 return b, nil
52}
53
54func unmarshalMessageSet(b []byte, m protoreflect.Message, o UnmarshalOptions) error {
Joe Tsai1799d112019-08-08 13:31:59 -070055 if !flags.ProtoLegacy {
Damien Neil302cb322019-06-19 15:22:13 -070056 return errors.New("no support for message_set_wire_format")
57 }
Damien Neilce3384c2019-11-06 13:18:28 -080058 return messageset.Unmarshal(b, false, func(num wire.Number, v []byte) error {
59 err := unmarshalMessageSetField(m, num, v, o)
Damien Neil302cb322019-06-19 15:22:13 -070060 if err == errUnknown {
Damien Neilce3384c2019-11-06 13:18:28 -080061 unknown := m.GetUnknown()
62 unknown = wire.AppendTag(unknown, num, wire.BytesType)
63 unknown = wire.AppendBytes(unknown, v)
64 m.SetUnknown(unknown)
65 return nil
Damien Neil302cb322019-06-19 15:22:13 -070066 }
Damien Neilce3384c2019-11-06 13:18:28 -080067 return err
68 })
69}
70
71func unmarshalMessageSetField(m protoreflect.Message, num wire.Number, v []byte, o UnmarshalOptions) error {
72 md := m.Descriptor()
73 if !md.ExtensionRanges().Has(num) {
74 return errUnknown
75 }
76 xt, err := o.Resolver.FindExtensionByNumber(md.FullName(), num)
77 if err == protoregistry.NotFound {
78 return errUnknown
79 }
80 if err != nil {
81 return err
82 }
83 xd := xt.TypeDescriptor()
84 if err := o.unmarshalMessage(v, m.Mutable(xd).Message()); err != nil {
85 return err
Damien Neil302cb322019-06-19 15:22:13 -070086 }
87 return nil
88}