blob: b6b3de59116e11a2a7772b684fac871aed3a8318 [file] [log] [blame]
Takahiro Suzuki241c10e2020-12-17 20:17:57 +09001// 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/encoding/protowire"
9 "google.golang.org/protobuf/internal/encoding/messageset"
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 += protowire.SizeTag(messageset.FieldMessage)
20 size += protowire.SizeBytes(sizeMessage(v.Message()))
21 return true
22 })
23 size += messageset.SizeUnknown(m.GetUnknown())
24 return size
25}
26
27func marshalMessageSet(b []byte, m protoreflect.Message, o MarshalOptions) ([]byte, error) {
28 if !flags.ProtoLegacy {
29 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 }
39 return messageset.AppendUnknown(b, m.GetUnknown())
40}
41
42func marshalMessageSetField(b []byte, fd protoreflect.FieldDescriptor, value protoreflect.Value, o MarshalOptions) ([]byte, error) {
43 b = messageset.AppendFieldStart(b, fd.Number())
44 b = protowire.AppendTag(b, messageset.FieldMessage, protowire.BytesType)
45 b = protowire.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 {
55 if !flags.ProtoLegacy {
56 return errors.New("no support for message_set_wire_format")
57 }
58 return messageset.Unmarshal(b, false, func(num protowire.Number, v []byte) error {
59 err := unmarshalMessageSetField(m, num, v, o)
60 if err == errUnknown {
61 unknown := m.GetUnknown()
62 unknown = protowire.AppendTag(unknown, num, protowire.BytesType)
63 unknown = protowire.AppendBytes(unknown, v)
64 m.SetUnknown(unknown)
65 return nil
66 }
67 return err
68 })
69}
70
71func unmarshalMessageSetField(m protoreflect.Message, num protowire.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 errors.New("%v: unable to resolve extension %v: %v", md.FullName(), num, err)
82 }
83 xd := xt.TypeDescriptor()
84 if err := o.unmarshalMessage(v, m.Mutable(xd).Message()); err != nil {
85 return err
86 }
87 return nil
88}