podman

Форк
0
284 строки · 8.5 Кб
1
// Copyright 2018 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
	"fmt"
9
	"reflect"
10
	"strconv"
11
	"strings"
12
	"sync"
13
	"sync/atomic"
14

15
	"google.golang.org/protobuf/internal/genid"
16
	"google.golang.org/protobuf/reflect/protoreflect"
17
	"google.golang.org/protobuf/reflect/protoregistry"
18
)
19

20
// MessageInfo provides protobuf related functionality for a given Go type
21
// that represents a message. A given instance of MessageInfo is tied to
22
// exactly one Go type, which must be a pointer to a struct type.
23
//
24
// The exported fields must be populated before any methods are called
25
// and cannot be mutated after set.
26
type MessageInfo struct {
27
	// GoReflectType is the underlying message Go type and must be populated.
28
	GoReflectType reflect.Type // pointer to struct
29

30
	// Desc is the underlying message descriptor type and must be populated.
31
	Desc protoreflect.MessageDescriptor
32

33
	// Exporter must be provided in a purego environment in order to provide
34
	// access to unexported fields.
35
	Exporter exporter
36

37
	// OneofWrappers is list of pointers to oneof wrapper struct types.
38
	OneofWrappers []interface{}
39

40
	initMu   sync.Mutex // protects all unexported fields
41
	initDone uint32
42

43
	reflectMessageInfo // for reflection implementation
44
	coderMessageInfo   // for fast-path method implementations
45
}
46

47
// exporter is a function that returns a reference to the ith field of v,
48
// where v is a pointer to a struct. It returns nil if it does not support
49
// exporting the requested field (e.g., already exported).
50
type exporter func(v interface{}, i int) interface{}
51

52
// getMessageInfo returns the MessageInfo for any message type that
53
// is generated by our implementation of protoc-gen-go (for v2 and on).
54
// If it is unable to obtain a MessageInfo, it returns nil.
55
func getMessageInfo(mt reflect.Type) *MessageInfo {
56
	m, ok := reflect.Zero(mt).Interface().(protoreflect.ProtoMessage)
57
	if !ok {
58
		return nil
59
	}
60
	mr, ok := m.ProtoReflect().(interface{ ProtoMessageInfo() *MessageInfo })
61
	if !ok {
62
		return nil
63
	}
64
	return mr.ProtoMessageInfo()
65
}
66

67
func (mi *MessageInfo) init() {
68
	// This function is called in the hot path. Inline the sync.Once logic,
69
	// since allocating a closure for Once.Do is expensive.
70
	// Keep init small to ensure that it can be inlined.
71
	if atomic.LoadUint32(&mi.initDone) == 0 {
72
		mi.initOnce()
73
	}
74
}
75

76
func (mi *MessageInfo) initOnce() {
77
	mi.initMu.Lock()
78
	defer mi.initMu.Unlock()
79
	if mi.initDone == 1 {
80
		return
81
	}
82

83
	t := mi.GoReflectType
84
	if t.Kind() != reflect.Ptr && t.Elem().Kind() != reflect.Struct {
85
		panic(fmt.Sprintf("got %v, want *struct kind", t))
86
	}
87
	t = t.Elem()
88

89
	si := mi.makeStructInfo(t)
90
	mi.makeReflectFuncs(t, si)
91
	mi.makeCoderMethods(t, si)
92

93
	atomic.StoreUint32(&mi.initDone, 1)
94
}
95

96
// getPointer returns the pointer for a message, which should be of
97
// the type of the MessageInfo. If the message is of a different type,
98
// it returns ok==false.
99
func (mi *MessageInfo) getPointer(m protoreflect.Message) (p pointer, ok bool) {
100
	switch m := m.(type) {
101
	case *messageState:
102
		return m.pointer(), m.messageInfo() == mi
103
	case *messageReflectWrapper:
104
		return m.pointer(), m.messageInfo() == mi
105
	}
106
	return pointer{}, false
107
}
108

109
type (
110
	SizeCache       = int32
111
	WeakFields      = map[int32]protoreflect.ProtoMessage
112
	UnknownFields   = unknownFieldsA // TODO: switch to unknownFieldsB
113
	unknownFieldsA  = []byte
114
	unknownFieldsB  = *[]byte
115
	ExtensionFields = map[int32]ExtensionField
116
)
117

118
var (
119
	sizecacheType       = reflect.TypeOf(SizeCache(0))
120
	weakFieldsType      = reflect.TypeOf(WeakFields(nil))
121
	unknownFieldsAType  = reflect.TypeOf(unknownFieldsA(nil))
122
	unknownFieldsBType  = reflect.TypeOf(unknownFieldsB(nil))
123
	extensionFieldsType = reflect.TypeOf(ExtensionFields(nil))
124
)
125

126
type structInfo struct {
127
	sizecacheOffset offset
128
	sizecacheType   reflect.Type
129
	weakOffset      offset
130
	weakType        reflect.Type
131
	unknownOffset   offset
132
	unknownType     reflect.Type
133
	extensionOffset offset
134
	extensionType   reflect.Type
135

136
	fieldsByNumber        map[protoreflect.FieldNumber]reflect.StructField
137
	oneofsByName          map[protoreflect.Name]reflect.StructField
138
	oneofWrappersByType   map[reflect.Type]protoreflect.FieldNumber
139
	oneofWrappersByNumber map[protoreflect.FieldNumber]reflect.Type
140
}
141

142
func (mi *MessageInfo) makeStructInfo(t reflect.Type) structInfo {
143
	si := structInfo{
144
		sizecacheOffset: invalidOffset,
145
		weakOffset:      invalidOffset,
146
		unknownOffset:   invalidOffset,
147
		extensionOffset: invalidOffset,
148

149
		fieldsByNumber:        map[protoreflect.FieldNumber]reflect.StructField{},
150
		oneofsByName:          map[protoreflect.Name]reflect.StructField{},
151
		oneofWrappersByType:   map[reflect.Type]protoreflect.FieldNumber{},
152
		oneofWrappersByNumber: map[protoreflect.FieldNumber]reflect.Type{},
153
	}
154

155
fieldLoop:
156
	for i := 0; i < t.NumField(); i++ {
157
		switch f := t.Field(i); f.Name {
158
		case genid.SizeCache_goname, genid.SizeCacheA_goname:
159
			if f.Type == sizecacheType {
160
				si.sizecacheOffset = offsetOf(f, mi.Exporter)
161
				si.sizecacheType = f.Type
162
			}
163
		case genid.WeakFields_goname, genid.WeakFieldsA_goname:
164
			if f.Type == weakFieldsType {
165
				si.weakOffset = offsetOf(f, mi.Exporter)
166
				si.weakType = f.Type
167
			}
168
		case genid.UnknownFields_goname, genid.UnknownFieldsA_goname:
169
			if f.Type == unknownFieldsAType || f.Type == unknownFieldsBType {
170
				si.unknownOffset = offsetOf(f, mi.Exporter)
171
				si.unknownType = f.Type
172
			}
173
		case genid.ExtensionFields_goname, genid.ExtensionFieldsA_goname, genid.ExtensionFieldsB_goname:
174
			if f.Type == extensionFieldsType {
175
				si.extensionOffset = offsetOf(f, mi.Exporter)
176
				si.extensionType = f.Type
177
			}
178
		default:
179
			for _, s := range strings.Split(f.Tag.Get("protobuf"), ",") {
180
				if len(s) > 0 && strings.Trim(s, "0123456789") == "" {
181
					n, _ := strconv.ParseUint(s, 10, 64)
182
					si.fieldsByNumber[protoreflect.FieldNumber(n)] = f
183
					continue fieldLoop
184
				}
185
			}
186
			if s := f.Tag.Get("protobuf_oneof"); len(s) > 0 {
187
				si.oneofsByName[protoreflect.Name(s)] = f
188
				continue fieldLoop
189
			}
190
		}
191
	}
192

193
	// Derive a mapping of oneof wrappers to fields.
194
	oneofWrappers := mi.OneofWrappers
195
	methods := make([]reflect.Method, 0, 2)
196
	if m, ok := reflect.PtrTo(t).MethodByName("XXX_OneofFuncs"); ok {
197
		methods = append(methods, m)
198
	}
199
	if m, ok := reflect.PtrTo(t).MethodByName("XXX_OneofWrappers"); ok {
200
		methods = append(methods, m)
201
	}
202
	for _, fn := range methods {
203
		for _, v := range fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))}) {
204
			if vs, ok := v.Interface().([]interface{}); ok {
205
				oneofWrappers = vs
206
			}
207
		}
208
	}
209
	for _, v := range oneofWrappers {
210
		tf := reflect.TypeOf(v).Elem()
211
		f := tf.Field(0)
212
		for _, s := range strings.Split(f.Tag.Get("protobuf"), ",") {
213
			if len(s) > 0 && strings.Trim(s, "0123456789") == "" {
214
				n, _ := strconv.ParseUint(s, 10, 64)
215
				si.oneofWrappersByType[tf] = protoreflect.FieldNumber(n)
216
				si.oneofWrappersByNumber[protoreflect.FieldNumber(n)] = tf
217
				break
218
			}
219
		}
220
	}
221

222
	return si
223
}
224

225
func (mi *MessageInfo) New() protoreflect.Message {
226
	m := reflect.New(mi.GoReflectType.Elem()).Interface()
227
	if r, ok := m.(protoreflect.ProtoMessage); ok {
228
		return r.ProtoReflect()
229
	}
230
	return mi.MessageOf(m)
231
}
232
func (mi *MessageInfo) Zero() protoreflect.Message {
233
	return mi.MessageOf(reflect.Zero(mi.GoReflectType).Interface())
234
}
235
func (mi *MessageInfo) Descriptor() protoreflect.MessageDescriptor {
236
	return mi.Desc
237
}
238
func (mi *MessageInfo) Enum(i int) protoreflect.EnumType {
239
	mi.init()
240
	fd := mi.Desc.Fields().Get(i)
241
	return Export{}.EnumTypeOf(mi.fieldTypes[fd.Number()])
242
}
243
func (mi *MessageInfo) Message(i int) protoreflect.MessageType {
244
	mi.init()
245
	fd := mi.Desc.Fields().Get(i)
246
	switch {
247
	case fd.IsWeak():
248
		mt, _ := protoregistry.GlobalTypes.FindMessageByName(fd.Message().FullName())
249
		return mt
250
	case fd.IsMap():
251
		return mapEntryType{fd.Message(), mi.fieldTypes[fd.Number()]}
252
	default:
253
		return Export{}.MessageTypeOf(mi.fieldTypes[fd.Number()])
254
	}
255
}
256

257
type mapEntryType struct {
258
	desc    protoreflect.MessageDescriptor
259
	valType interface{} // zero value of enum or message type
260
}
261

262
func (mt mapEntryType) New() protoreflect.Message {
263
	return nil
264
}
265
func (mt mapEntryType) Zero() protoreflect.Message {
266
	return nil
267
}
268
func (mt mapEntryType) Descriptor() protoreflect.MessageDescriptor {
269
	return mt.desc
270
}
271
func (mt mapEntryType) Enum(i int) protoreflect.EnumType {
272
	fd := mt.desc.Fields().Get(i)
273
	if fd.Enum() == nil {
274
		return nil
275
	}
276
	return Export{}.EnumTypeOf(mt.valType)
277
}
278
func (mt mapEntryType) Message(i int) protoreflect.MessageType {
279
	fd := mt.desc.Fields().Get(i)
280
	if fd.Message() == nil {
281
		return nil
282
	}
283
	return Export{}.MessageTypeOf(mt.valType)
284
}
285

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.