1// Copyright 2020 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 protocmp
6
7import (
8	"reflect"
9	"sort"
10	"strconv"
11	"strings"
12
13	"google.golang.org/protobuf/internal/genid"
14	"google.golang.org/protobuf/proto"
15	"google.golang.org/protobuf/reflect/protoreflect"
16	"google.golang.org/protobuf/runtime/protoiface"
17)
18
19func reflectValueOf(v interface{}) protoreflect.Value {
20	switch v := v.(type) {
21	case Enum:
22		return protoreflect.ValueOfEnum(v.Number())
23	case Message:
24		return protoreflect.ValueOfMessage(v.ProtoReflect())
25	case []byte:
26		return protoreflect.ValueOfBytes(v) // avoid overlap with reflect.Slice check below
27	default:
28		switch rv := reflect.ValueOf(v); {
29		case rv.Kind() == reflect.Slice:
30			return protoreflect.ValueOfList(reflectList{rv})
31		case rv.Kind() == reflect.Map:
32			return protoreflect.ValueOfMap(reflectMap{rv})
33		default:
34			return protoreflect.ValueOf(v)
35		}
36	}
37}
38
39type reflectMessage Message
40
41func (m reflectMessage) stringKey(fd protoreflect.FieldDescriptor) string {
42	if m.Descriptor() != fd.ContainingMessage() {
43		panic("mismatching containing message")
44	}
45	return fd.TextName()
46}
47
48func (m reflectMessage) Descriptor() protoreflect.MessageDescriptor {
49	return (Message)(m).Descriptor()
50}
51func (m reflectMessage) Type() protoreflect.MessageType {
52	return reflectMessageType{m.Descriptor()}
53}
54func (m reflectMessage) New() protoreflect.Message {
55	return m.Type().New()
56}
57func (m reflectMessage) Interface() protoreflect.ProtoMessage {
58	return Message(m)
59}
60func (m reflectMessage) Range(f func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool) {
61	// Range over populated known fields.
62	fds := m.Descriptor().Fields()
63	for i := 0; i < fds.Len(); i++ {
64		fd := fds.Get(i)
65		if m.Has(fd) && !f(fd, m.Get(fd)) {
66			return
67		}
68	}
69
70	// Range over populated extension fields.
71	for _, xd := range m[messageTypeKey].(messageType).xds {
72		if m.Has(xd) && !f(xd, m.Get(xd)) {
73			return
74		}
75	}
76}
77func (m reflectMessage) Has(fd protoreflect.FieldDescriptor) bool {
78	_, ok := m[m.stringKey(fd)]
79	return ok
80}
81func (m reflectMessage) Clear(protoreflect.FieldDescriptor) {
82	panic("invalid mutation of read-only message")
83}
84func (m reflectMessage) Get(fd protoreflect.FieldDescriptor) protoreflect.Value {
85	v, ok := m[m.stringKey(fd)]
86	if !ok {
87		switch {
88		case fd.IsList():
89			return protoreflect.ValueOfList(reflectList{})
90		case fd.IsMap():
91			return protoreflect.ValueOfMap(reflectMap{})
92		case fd.Message() != nil:
93			return protoreflect.ValueOfMessage(reflectMessage{
94				messageTypeKey: messageType{md: m.Descriptor()},
95			})
96		default:
97			return fd.Default()
98		}
99	}
100
101	// The transformation may leave Any messages in structured form.
102	// If so, convert them back to a raw-encoded form.
103	if fd.FullName() == genid.Any_Value_field_fullname {
104		if m, ok := v.(Message); ok {
105			b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
106			if err != nil {
107				panic("BUG: " + err.Error())
108			}
109			return protoreflect.ValueOfBytes(b)
110		}
111	}
112
113	return reflectValueOf(v)
114}
115func (m reflectMessage) Set(protoreflect.FieldDescriptor, protoreflect.Value) {
116	panic("invalid mutation of read-only message")
117}
118func (m reflectMessage) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value {
119	panic("invalid mutation of read-only message")
120}
121func (m reflectMessage) NewField(protoreflect.FieldDescriptor) protoreflect.Value {
122	panic("not implemented")
123}
124func (m reflectMessage) WhichOneof(od protoreflect.OneofDescriptor) protoreflect.FieldDescriptor {
125	if m.Descriptor().Oneofs().ByName(od.Name()) != od {
126		panic("oneof descriptor does not belong to this message")
127	}
128	fds := od.Fields()
129	for i := 0; i < fds.Len(); i++ {
130		fd := fds.Get(i)
131		if _, ok := m[m.stringKey(fd)]; ok {
132			return fd
133		}
134	}
135	return nil
136}
137func (m reflectMessage) GetUnknown() protoreflect.RawFields {
138	var nums []protoreflect.FieldNumber
139	for k := range m {
140		if len(strings.Trim(k, "0123456789")) == 0 {
141			n, _ := strconv.ParseUint(k, 10, 32)
142			nums = append(nums, protoreflect.FieldNumber(n))
143		}
144	}
145	sort.Slice(nums, func(i, j int) bool { return nums[i] < nums[j] })
146
147	var raw protoreflect.RawFields
148	for _, num := range nums {
149		b, _ := m[strconv.FormatUint(uint64(num), 10)].(protoreflect.RawFields)
150		raw = append(raw, b...)
151	}
152	return raw
153}
154func (m reflectMessage) SetUnknown(protoreflect.RawFields) {
155	panic("invalid mutation of read-only message")
156}
157func (m reflectMessage) IsValid() bool {
158	invalid, _ := m[messageInvalidKey].(bool)
159	return !invalid
160}
161func (m reflectMessage) ProtoMethods() *protoiface.Methods {
162	return nil
163}
164
165type reflectMessageType struct{ protoreflect.MessageDescriptor }
166
167func (t reflectMessageType) New() protoreflect.Message {
168	panic("not implemented")
169}
170func (t reflectMessageType) Zero() protoreflect.Message {
171	panic("not implemented")
172}
173func (t reflectMessageType) Descriptor() protoreflect.MessageDescriptor {
174	return t.MessageDescriptor
175}
176
177type reflectList struct{ v reflect.Value }
178
179func (ls reflectList) Len() int {
180	if !ls.IsValid() {
181		return 0
182	}
183	return ls.v.Len()
184}
185func (ls reflectList) Get(i int) protoreflect.Value {
186	return reflectValueOf(ls.v.Index(i).Interface())
187}
188func (ls reflectList) Set(int, protoreflect.Value) {
189	panic("invalid mutation of read-only list")
190}
191func (ls reflectList) Append(protoreflect.Value) {
192	panic("invalid mutation of read-only list")
193}
194func (ls reflectList) AppendMutable() protoreflect.Value {
195	panic("invalid mutation of read-only list")
196}
197func (ls reflectList) Truncate(int) {
198	panic("invalid mutation of read-only list")
199}
200func (ls reflectList) NewElement() protoreflect.Value {
201	panic("not implemented")
202}
203func (ls reflectList) IsValid() bool {
204	return ls.v.IsValid()
205}
206
207type reflectMap struct{ v reflect.Value }
208
209func (ms reflectMap) Len() int {
210	if !ms.IsValid() {
211		return 0
212	}
213	return ms.v.Len()
214}
215func (ms reflectMap) Range(f func(protoreflect.MapKey, protoreflect.Value) bool) {
216	if !ms.IsValid() {
217		return
218	}
219	ks := ms.v.MapKeys()
220	for _, k := range ks {
221		pk := reflectValueOf(k.Interface()).MapKey()
222		pv := reflectValueOf(ms.v.MapIndex(k).Interface())
223		if !f(pk, pv) {
224			return
225		}
226	}
227}
228func (ms reflectMap) Has(k protoreflect.MapKey) bool {
229	if !ms.IsValid() {
230		return false
231	}
232	return ms.v.MapIndex(reflect.ValueOf(k.Interface())).IsValid()
233}
234func (ms reflectMap) Clear(protoreflect.MapKey) {
235	panic("invalid mutation of read-only list")
236}
237func (ms reflectMap) Get(k protoreflect.MapKey) protoreflect.Value {
238	if !ms.IsValid() {
239		return protoreflect.Value{}
240	}
241	v := ms.v.MapIndex(reflect.ValueOf(k.Interface()))
242	if !v.IsValid() {
243		return protoreflect.Value{}
244	}
245	return reflectValueOf(v.Interface())
246}
247func (ms reflectMap) Set(protoreflect.MapKey, protoreflect.Value) {
248	panic("invalid mutation of read-only list")
249}
250func (ms reflectMap) Mutable(k protoreflect.MapKey) protoreflect.Value {
251	panic("invalid mutation of read-only list")
252}
253func (ms reflectMap) NewValue() protoreflect.Value {
254	panic("not implemented")
255}
256func (ms reflectMap) IsValid() bool {
257	return ms.v.IsValid()
258}
259