256
|
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 |
"reflect" |
|
9 |
|
|
10 |
"google.golang.org/protobuf/internal/descopts" |
|
11 |
"google.golang.org/protobuf/internal/encoding/messageset" |
|
12 |
ptag "google.golang.org/protobuf/internal/encoding/tag" |
|
13 |
"google.golang.org/protobuf/internal/filedesc" |
|
14 |
"google.golang.org/protobuf/internal/pragma" |
260
|
15 |
"google.golang.org/protobuf/reflect/protoreflect" |
|
16 |
"google.golang.org/protobuf/reflect/protoregistry" |
|
17 |
"google.golang.org/protobuf/runtime/protoiface" |
256
|
18 |
) |
|
19 |
|
|
20 |
func (xi *ExtensionInfo) initToLegacy() { |
|
21 |
xd := xi.desc |
260
|
22 |
var parent protoiface.MessageV1 |
256
|
23 |
messageName := xd.ContainingMessage().FullName() |
260
|
24 |
if mt, _ := protoregistry.GlobalTypes.FindMessageByName(messageName); mt != nil { |
256
|
25 |
// Create a new parent message and unwrap it if possible. |
|
26 |
mv := mt.New().Interface() |
|
27 |
t := reflect.TypeOf(mv) |
|
28 |
if mv, ok := mv.(unwrapper); ok { |
|
29 |
t = reflect.TypeOf(mv.protoUnwrap()) |
|
30 |
} |
|
31 |
|
|
32 |
// Check whether the message implements the legacy v1 Message interface. |
|
33 |
mz := reflect.Zero(t).Interface() |
260
|
34 |
if mz, ok := mz.(protoiface.MessageV1); ok { |
256
|
35 |
parent = mz |
|
36 |
} |
|
37 |
} |
|
38 |
|
|
39 |
// Determine the v1 extension type, which is unfortunately not the same as |
|
40 |
// the v2 ExtensionType.GoType. |
|
41 |
extType := xi.goType |
|
42 |
switch extType.Kind() { |
|
43 |
case reflect.Bool, reflect.Int32, reflect.Int64, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64, reflect.String: |
|
44 |
extType = reflect.PtrTo(extType) // T -> *T for singular scalar fields |
|
45 |
} |
|
46 |
|
|
47 |
// Reconstruct the legacy enum full name. |
|
48 |
var enumName string |
260
|
49 |
if xd.Kind() == protoreflect.EnumKind { |
256
|
50 |
enumName = legacyEnumName(xd.Enum()) |
|
51 |
} |
|
52 |
|
|
53 |
// Derive the proto file that the extension was declared within. |
|
54 |
var filename string |
|
55 |
if fd := xd.ParentFile(); fd != nil { |
|
56 |
filename = fd.Path() |
|
57 |
} |
|
58 |
|
|
59 |
// For MessageSet extensions, the name used is the parent message. |
|
60 |
name := xd.FullName() |
|
61 |
if messageset.IsMessageSetExtension(xd) { |
|
62 |
name = name.Parent() |
|
63 |
} |
|
64 |
|
|
65 |
xi.ExtendedType = parent |
|
66 |
xi.ExtensionType = reflect.Zero(extType).Interface() |
|
67 |
xi.Field = int32(xd.Number()) |
|
68 |
xi.Name = string(name) |
|
69 |
xi.Tag = ptag.Marshal(xd, enumName) |
|
70 |
xi.Filename = filename |
|
71 |
} |
|
72 |
|
|
73 |
// initFromLegacy initializes an ExtensionInfo from |
|
74 |
// the contents of the deprecated exported fields of the type. |
|
75 |
func (xi *ExtensionInfo) initFromLegacy() { |
|
76 |
// The v1 API returns "type incomplete" descriptors where only the |
|
77 |
// field number is specified. In such a case, use a placeholder. |
|
78 |
if xi.ExtendedType == nil || xi.ExtensionType == nil { |
|
79 |
xd := placeholderExtension{ |
260
|
80 |
name: protoreflect.FullName(xi.Name), |
|
81 |
number: protoreflect.FieldNumber(xi.Field), |
256
|
82 |
} |
|
83 |
xi.desc = extensionTypeDescriptor{xd, xi} |
|
84 |
return |
|
85 |
} |
|
86 |
|
|
87 |
// Resolve enum or message dependencies. |
260
|
88 |
var ed protoreflect.EnumDescriptor |
|
89 |
var md protoreflect.MessageDescriptor |
256
|
90 |
t := reflect.TypeOf(xi.ExtensionType) |
|
91 |
isOptional := t.Kind() == reflect.Ptr && t.Elem().Kind() != reflect.Struct |
|
92 |
isRepeated := t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8 |
|
93 |
if isOptional || isRepeated { |
|
94 |
t = t.Elem() |
|
95 |
} |
|
96 |
switch v := reflect.Zero(t).Interface().(type) { |
260
|
97 |
case protoreflect.Enum: |
256
|
98 |
ed = v.Descriptor() |
|
99 |
case enumV1: |
|
100 |
ed = LegacyLoadEnumDesc(t) |
260
|
101 |
case protoreflect.ProtoMessage: |
256
|
102 |
md = v.ProtoReflect().Descriptor() |
|
103 |
case messageV1: |
|
104 |
md = LegacyLoadMessageDesc(t) |
|
105 |
} |
|
106 |
|
|
107 |
// Derive basic field information from the struct tag. |
260
|
108 |
var evs protoreflect.EnumValueDescriptors |
256
|
109 |
if ed != nil { |
|
110 |
evs = ed.Values() |
|
111 |
} |
|
112 |
fd := ptag.Unmarshal(xi.Tag, t, evs).(*filedesc.Field) |
|
113 |
|
|
114 |
// Construct a v2 ExtensionType. |
|
115 |
xd := &filedesc.Extension{L2: new(filedesc.ExtensionL2)} |
|
116 |
xd.L0.ParentFile = filedesc.SurrogateProto2 |
260
|
117 |
xd.L0.FullName = protoreflect.FullName(xi.Name) |
|
118 |
xd.L1.Number = protoreflect.FieldNumber(xi.Field) |
256
|
119 |
xd.L1.Cardinality = fd.L1.Cardinality |
|
120 |
xd.L1.Kind = fd.L1.Kind |
|
121 |
xd.L2.IsPacked = fd.L1.IsPacked |
|
122 |
xd.L2.Default = fd.L1.Default |
|
123 |
xd.L1.Extendee = Export{}.MessageDescriptorOf(xi.ExtendedType) |
|
124 |
xd.L2.Enum = ed |
|
125 |
xd.L2.Message = md |
|
126 |
|
|
127 |
// Derive real extension field name for MessageSets. |
|
128 |
if messageset.IsMessageSet(xd.L1.Extendee) && md.FullName() == xd.L0.FullName { |
|
129 |
xd.L0.FullName = xd.L0.FullName.Append(messageset.ExtensionName) |
|
130 |
} |
|
131 |
|
|
132 |
tt := reflect.TypeOf(xi.ExtensionType) |
|
133 |
if isOptional { |
|
134 |
tt = tt.Elem() |
|
135 |
} |
|
136 |
xi.goType = tt |
|
137 |
xi.desc = extensionTypeDescriptor{xd, xi} |
|
138 |
} |
|
139 |
|
|
140 |
type placeholderExtension struct { |
260
|
141 |
name protoreflect.FullName |
|
142 |
number protoreflect.FieldNumber |
256
|
143 |
} |
|
144 |
|
260
|
145 |
func (x placeholderExtension) ParentFile() protoreflect.FileDescriptor { return nil } |
|
146 |
func (x placeholderExtension) Parent() protoreflect.Descriptor { return nil } |
|
147 |
func (x placeholderExtension) Index() int { return 0 } |
|
148 |
func (x placeholderExtension) Syntax() protoreflect.Syntax { return 0 } |
|
149 |
func (x placeholderExtension) Name() protoreflect.Name { return x.name.Name() } |
|
150 |
func (x placeholderExtension) FullName() protoreflect.FullName { return x.name } |
|
151 |
func (x placeholderExtension) IsPlaceholder() bool { return true } |
|
152 |
func (x placeholderExtension) Options() protoreflect.ProtoMessage { return descopts.Field } |
|
153 |
func (x placeholderExtension) Number() protoreflect.FieldNumber { return x.number } |
|
154 |
func (x placeholderExtension) Cardinality() protoreflect.Cardinality { return 0 } |
|
155 |
func (x placeholderExtension) Kind() protoreflect.Kind { return 0 } |
|
156 |
func (x placeholderExtension) HasJSONName() bool { return false } |
|
157 |
func (x placeholderExtension) JSONName() string { return "[" + string(x.name) + "]" } |
|
158 |
func (x placeholderExtension) TextName() string { return "[" + string(x.name) + "]" } |
|
159 |
func (x placeholderExtension) HasPresence() bool { return false } |
|
160 |
func (x placeholderExtension) HasOptionalKeyword() bool { return false } |
|
161 |
func (x placeholderExtension) IsExtension() bool { return true } |
|
162 |
func (x placeholderExtension) IsWeak() bool { return false } |
|
163 |
func (x placeholderExtension) IsPacked() bool { return false } |
|
164 |
func (x placeholderExtension) IsList() bool { return false } |
|
165 |
func (x placeholderExtension) IsMap() bool { return false } |
|
166 |
func (x placeholderExtension) MapKey() protoreflect.FieldDescriptor { return nil } |
|
167 |
func (x placeholderExtension) MapValue() protoreflect.FieldDescriptor { return nil } |
|
168 |
func (x placeholderExtension) HasDefault() bool { return false } |
|
169 |
func (x placeholderExtension) Default() protoreflect.Value { return protoreflect.Value{} } |
|
170 |
func (x placeholderExtension) DefaultEnumValue() protoreflect.EnumValueDescriptor { return nil } |
|
171 |
func (x placeholderExtension) ContainingOneof() protoreflect.OneofDescriptor { return nil } |
|
172 |
func (x placeholderExtension) ContainingMessage() protoreflect.MessageDescriptor { return nil } |
|
173 |
func (x placeholderExtension) Enum() protoreflect.EnumDescriptor { return nil } |
|
174 |
func (x placeholderExtension) Message() protoreflect.MessageDescriptor { return nil } |
|
175 |
func (x placeholderExtension) ProtoType(protoreflect.FieldDescriptor) { return } |
|
176 |
func (x placeholderExtension) ProtoInternal(pragma.DoNotImplement) { return } |