12 "sync" |
12 "sync" |
13 "sync/atomic" |
13 "sync/atomic" |
14 |
14 |
15 "google.golang.org/protobuf/internal/genid" |
15 "google.golang.org/protobuf/internal/genid" |
16 "google.golang.org/protobuf/reflect/protoreflect" |
16 "google.golang.org/protobuf/reflect/protoreflect" |
17 pref "google.golang.org/protobuf/reflect/protoreflect" |
17 "google.golang.org/protobuf/reflect/protoregistry" |
18 preg "google.golang.org/protobuf/reflect/protoregistry" |
|
19 ) |
18 ) |
20 |
19 |
21 // MessageInfo provides protobuf related functionality for a given Go type |
20 // MessageInfo provides protobuf related functionality for a given Go type |
22 // that represents a message. A given instance of MessageInfo is tied to |
21 // that represents a message. A given instance of MessageInfo is tied to |
23 // exactly one Go type, which must be a pointer to a struct type. |
22 // exactly one Go type, which must be a pointer to a struct type. |
27 type MessageInfo struct { |
26 type MessageInfo struct { |
28 // GoReflectType is the underlying message Go type and must be populated. |
27 // GoReflectType is the underlying message Go type and must be populated. |
29 GoReflectType reflect.Type // pointer to struct |
28 GoReflectType reflect.Type // pointer to struct |
30 |
29 |
31 // Desc is the underlying message descriptor type and must be populated. |
30 // Desc is the underlying message descriptor type and must be populated. |
32 Desc pref.MessageDescriptor |
31 Desc protoreflect.MessageDescriptor |
33 |
32 |
34 // Exporter must be provided in a purego environment in order to provide |
33 // Exporter must be provided in a purego environment in order to provide |
35 // access to unexported fields. |
34 // access to unexported fields. |
36 Exporter exporter |
35 Exporter exporter |
37 |
36 |
52 |
51 |
53 // getMessageInfo returns the MessageInfo for any message type that |
52 // getMessageInfo returns the MessageInfo for any message type that |
54 // is generated by our implementation of protoc-gen-go (for v2 and on). |
53 // is generated by our implementation of protoc-gen-go (for v2 and on). |
55 // If it is unable to obtain a MessageInfo, it returns nil. |
54 // If it is unable to obtain a MessageInfo, it returns nil. |
56 func getMessageInfo(mt reflect.Type) *MessageInfo { |
55 func getMessageInfo(mt reflect.Type) *MessageInfo { |
57 m, ok := reflect.Zero(mt).Interface().(pref.ProtoMessage) |
56 m, ok := reflect.Zero(mt).Interface().(protoreflect.ProtoMessage) |
58 if !ok { |
57 if !ok { |
59 return nil |
58 return nil |
60 } |
59 } |
61 mr, ok := m.ProtoReflect().(interface{ ProtoMessageInfo() *MessageInfo }) |
60 mr, ok := m.ProtoReflect().(interface{ ProtoMessageInfo() *MessageInfo }) |
62 if !ok { |
61 if !ok { |
95 } |
94 } |
96 |
95 |
97 // getPointer returns the pointer for a message, which should be of |
96 // getPointer returns the pointer for a message, which should be of |
98 // the type of the MessageInfo. If the message is of a different type, |
97 // the type of the MessageInfo. If the message is of a different type, |
99 // it returns ok==false. |
98 // it returns ok==false. |
100 func (mi *MessageInfo) getPointer(m pref.Message) (p pointer, ok bool) { |
99 func (mi *MessageInfo) getPointer(m protoreflect.Message) (p pointer, ok bool) { |
101 switch m := m.(type) { |
100 switch m := m.(type) { |
102 case *messageState: |
101 case *messageState: |
103 return m.pointer(), m.messageInfo() == mi |
102 return m.pointer(), m.messageInfo() == mi |
104 case *messageReflectWrapper: |
103 case *messageReflectWrapper: |
105 return m.pointer(), m.messageInfo() == mi |
104 return m.pointer(), m.messageInfo() == mi |
132 unknownOffset offset |
131 unknownOffset offset |
133 unknownType reflect.Type |
132 unknownType reflect.Type |
134 extensionOffset offset |
133 extensionOffset offset |
135 extensionType reflect.Type |
134 extensionType reflect.Type |
136 |
135 |
137 fieldsByNumber map[pref.FieldNumber]reflect.StructField |
136 fieldsByNumber map[protoreflect.FieldNumber]reflect.StructField |
138 oneofsByName map[pref.Name]reflect.StructField |
137 oneofsByName map[protoreflect.Name]reflect.StructField |
139 oneofWrappersByType map[reflect.Type]pref.FieldNumber |
138 oneofWrappersByType map[reflect.Type]protoreflect.FieldNumber |
140 oneofWrappersByNumber map[pref.FieldNumber]reflect.Type |
139 oneofWrappersByNumber map[protoreflect.FieldNumber]reflect.Type |
141 } |
140 } |
142 |
141 |
143 func (mi *MessageInfo) makeStructInfo(t reflect.Type) structInfo { |
142 func (mi *MessageInfo) makeStructInfo(t reflect.Type) structInfo { |
144 si := structInfo{ |
143 si := structInfo{ |
145 sizecacheOffset: invalidOffset, |
144 sizecacheOffset: invalidOffset, |
146 weakOffset: invalidOffset, |
145 weakOffset: invalidOffset, |
147 unknownOffset: invalidOffset, |
146 unknownOffset: invalidOffset, |
148 extensionOffset: invalidOffset, |
147 extensionOffset: invalidOffset, |
149 |
148 |
150 fieldsByNumber: map[pref.FieldNumber]reflect.StructField{}, |
149 fieldsByNumber: map[protoreflect.FieldNumber]reflect.StructField{}, |
151 oneofsByName: map[pref.Name]reflect.StructField{}, |
150 oneofsByName: map[protoreflect.Name]reflect.StructField{}, |
152 oneofWrappersByType: map[reflect.Type]pref.FieldNumber{}, |
151 oneofWrappersByType: map[reflect.Type]protoreflect.FieldNumber{}, |
153 oneofWrappersByNumber: map[pref.FieldNumber]reflect.Type{}, |
152 oneofWrappersByNumber: map[protoreflect.FieldNumber]reflect.Type{}, |
154 } |
153 } |
155 |
154 |
156 fieldLoop: |
155 fieldLoop: |
157 for i := 0; i < t.NumField(); i++ { |
156 for i := 0; i < t.NumField(); i++ { |
158 switch f := t.Field(i); f.Name { |
157 switch f := t.Field(i); f.Name { |
178 } |
177 } |
179 default: |
178 default: |
180 for _, s := range strings.Split(f.Tag.Get("protobuf"), ",") { |
179 for _, s := range strings.Split(f.Tag.Get("protobuf"), ",") { |
181 if len(s) > 0 && strings.Trim(s, "0123456789") == "" { |
180 if len(s) > 0 && strings.Trim(s, "0123456789") == "" { |
182 n, _ := strconv.ParseUint(s, 10, 64) |
181 n, _ := strconv.ParseUint(s, 10, 64) |
183 si.fieldsByNumber[pref.FieldNumber(n)] = f |
182 si.fieldsByNumber[protoreflect.FieldNumber(n)] = f |
184 continue fieldLoop |
183 continue fieldLoop |
185 } |
184 } |
186 } |
185 } |
187 if s := f.Tag.Get("protobuf_oneof"); len(s) > 0 { |
186 if s := f.Tag.Get("protobuf_oneof"); len(s) > 0 { |
188 si.oneofsByName[pref.Name(s)] = f |
187 si.oneofsByName[protoreflect.Name(s)] = f |
189 continue fieldLoop |
188 continue fieldLoop |
190 } |
189 } |
191 } |
190 } |
192 } |
191 } |
193 |
192 |
206 tf := reflect.TypeOf(v).Elem() |
205 tf := reflect.TypeOf(v).Elem() |
207 f := tf.Field(0) |
206 f := tf.Field(0) |
208 for _, s := range strings.Split(f.Tag.Get("protobuf"), ",") { |
207 for _, s := range strings.Split(f.Tag.Get("protobuf"), ",") { |
209 if len(s) > 0 && strings.Trim(s, "0123456789") == "" { |
208 if len(s) > 0 && strings.Trim(s, "0123456789") == "" { |
210 n, _ := strconv.ParseUint(s, 10, 64) |
209 n, _ := strconv.ParseUint(s, 10, 64) |
211 si.oneofWrappersByType[tf] = pref.FieldNumber(n) |
210 si.oneofWrappersByType[tf] = protoreflect.FieldNumber(n) |
212 si.oneofWrappersByNumber[pref.FieldNumber(n)] = tf |
211 si.oneofWrappersByNumber[protoreflect.FieldNumber(n)] = tf |
213 break |
212 break |
214 } |
213 } |
215 } |
214 } |
216 } |
215 } |
217 |
216 |
218 return si |
217 return si |
219 } |
218 } |
220 |
219 |
221 func (mi *MessageInfo) New() protoreflect.Message { |
220 func (mi *MessageInfo) New() protoreflect.Message { |
222 return mi.MessageOf(reflect.New(mi.GoReflectType.Elem()).Interface()) |
221 m := reflect.New(mi.GoReflectType.Elem()).Interface() |
|
222 if r, ok := m.(protoreflect.ProtoMessage); ok { |
|
223 return r.ProtoReflect() |
|
224 } |
|
225 return mi.MessageOf(m) |
223 } |
226 } |
224 func (mi *MessageInfo) Zero() protoreflect.Message { |
227 func (mi *MessageInfo) Zero() protoreflect.Message { |
225 return mi.MessageOf(reflect.Zero(mi.GoReflectType).Interface()) |
228 return mi.MessageOf(reflect.Zero(mi.GoReflectType).Interface()) |
226 } |
229 } |
227 func (mi *MessageInfo) Descriptor() protoreflect.MessageDescriptor { |
230 func (mi *MessageInfo) Descriptor() protoreflect.MessageDescriptor { |
235 func (mi *MessageInfo) Message(i int) protoreflect.MessageType { |
238 func (mi *MessageInfo) Message(i int) protoreflect.MessageType { |
236 mi.init() |
239 mi.init() |
237 fd := mi.Desc.Fields().Get(i) |
240 fd := mi.Desc.Fields().Get(i) |
238 switch { |
241 switch { |
239 case fd.IsWeak(): |
242 case fd.IsWeak(): |
240 mt, _ := preg.GlobalTypes.FindMessageByName(fd.Message().FullName()) |
243 mt, _ := protoregistry.GlobalTypes.FindMessageByName(fd.Message().FullName()) |
241 return mt |
244 return mt |
242 case fd.IsMap(): |
245 case fd.IsMap(): |
243 return mapEntryType{fd.Message(), mi.fieldTypes[fd.Number()]} |
246 return mapEntryType{fd.Message(), mi.fieldTypes[fd.Number()]} |
244 default: |
247 default: |
245 return Export{}.MessageTypeOf(mi.fieldTypes[fd.Number()]) |
248 return Export{}.MessageTypeOf(mi.fieldTypes[fd.Number()]) |