blob: 0979ec018c44f4877e5cd4d89f6f8da0987cce72 [file] [log] [blame]
Joe Tsai08e00302018-11-26 22:32:06 -08001// 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
Joe Tsai21ade492019-05-22 13:42:54 -04005package impl
Joe Tsai08e00302018-11-26 22:32:06 -08006
7import (
Joe Tsai08e00302018-11-26 22:32:06 -08008 "reflect"
9
Joe Tsai945a1702019-07-20 14:57:56 -070010 "google.golang.org/protobuf/internal/encoding/messageset"
Damien Neile89e6242019-05-13 23:55:40 -070011 ptag "google.golang.org/protobuf/internal/encoding/tag"
Joe Tsaid8881392019-06-06 13:01:53 -070012 "google.golang.org/protobuf/internal/filedesc"
Damien Neile89e6242019-05-13 23:55:40 -070013 pref "google.golang.org/protobuf/reflect/protoreflect"
14 preg "google.golang.org/protobuf/reflect/protoregistry"
15 piface "google.golang.org/protobuf/runtime/protoiface"
Joe Tsai08e00302018-11-26 22:32:06 -080016)
17
Damien Neilf1e905b2019-08-08 15:45:59 -070018func (xi *ExtensionInfo) initToLegacy() {
19 xd := xi.desc
Joe Tsai4fddeba2019-03-20 18:29:32 -070020 var parent piface.MessageV1
Damien Neil92f76182019-08-02 16:58:08 -070021 messageName := xd.ContainingMessage().FullName()
Joe Tsaiac31a352019-05-13 14:32:56 -070022 if mt, _ := preg.GlobalTypes.FindMessageByName(messageName); mt != nil {
Joe Tsai08e00302018-11-26 22:32:06 -080023 // Create a new parent message and unwrap it if possible.
Joe Tsai3bc7d6f2019-01-09 02:57:13 -080024 mv := mt.New().Interface()
Joe Tsai08e00302018-11-26 22:32:06 -080025 t := reflect.TypeOf(mv)
Joe Tsaifd528ff2019-09-03 16:30:39 -070026 if mv, ok := mv.(unwrapper); ok {
27 t = reflect.TypeOf(mv.protoUnwrap())
Joe Tsai08e00302018-11-26 22:32:06 -080028 }
29
30 // Check whether the message implements the legacy v1 Message interface.
31 mz := reflect.Zero(t).Interface()
Joe Tsai4fddeba2019-03-20 18:29:32 -070032 if mz, ok := mz.(piface.MessageV1); ok {
Joe Tsai08e00302018-11-26 22:32:06 -080033 parent = mz
34 }
35 }
36
37 // Determine the v1 extension type, which is unfortunately not the same as
38 // the v2 ExtensionType.GoType.
Damien Neilf1e905b2019-08-08 15:45:59 -070039 extType := xi.goType
Joe Tsai08e00302018-11-26 22:32:06 -080040 switch extType.Kind() {
41 case reflect.Bool, reflect.Int32, reflect.Int64, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64, reflect.String:
42 extType = reflect.PtrTo(extType) // T -> *T for singular scalar fields
Joe Tsai08e00302018-11-26 22:32:06 -080043 }
44
Joe Tsai2e7817f2019-08-23 12:18:57 -070045 // Reconstruct the legacy enum full name.
Joe Tsai08e00302018-11-26 22:32:06 -080046 var enumName string
Damien Neil92f76182019-08-02 16:58:08 -070047 if xd.Kind() == pref.EnumKind {
Joe Tsai2e7817f2019-08-23 12:18:57 -070048 enumName = legacyEnumName(xd.Enum())
Joe Tsai08e00302018-11-26 22:32:06 -080049 }
50
51 // Derive the proto file that the extension was declared within.
52 var filename string
Damien Neil92f76182019-08-02 16:58:08 -070053 if fd := xd.ParentFile(); fd != nil {
Joe Tsai08e00302018-11-26 22:32:06 -080054 filename = fd.Path()
55 }
56
Joe Tsai945a1702019-07-20 14:57:56 -070057 // For MessageSet extensions, the name used is the parent message.
58 name := xd.FullName()
59 if messageset.IsMessageSetExtension(xd) {
60 name = name.Parent()
61 }
62
Damien Neilf1e905b2019-08-08 15:45:59 -070063 xi.ExtendedType = parent
64 xi.ExtensionType = reflect.Zero(extType).Interface()
65 xi.Field = int32(xd.Number())
Joe Tsai945a1702019-07-20 14:57:56 -070066 xi.Name = string(name)
Damien Neilf1e905b2019-08-08 15:45:59 -070067 xi.Tag = ptag.Marshal(xd, enumName)
68 xi.Filename = filename
Joe Tsai08e00302018-11-26 22:32:06 -080069}
70
Damien Neilf1e905b2019-08-08 15:45:59 -070071// initFromLegacy initializes an ExtensionInfo from
72// the contents of the deprecated exported fields of the type.
73func (xi *ExtensionInfo) initFromLegacy() {
Joe Tsaid8881392019-06-06 13:01:53 -070074 // Resolve enum or message dependencies.
75 var ed pref.EnumDescriptor
76 var md pref.MessageDescriptor
Damien Neilf1e905b2019-08-08 15:45:59 -070077 t := reflect.TypeOf(xi.ExtensionType)
Joe Tsai08e00302018-11-26 22:32:06 -080078 isOptional := t.Kind() == reflect.Ptr && t.Elem().Kind() != reflect.Struct
79 isRepeated := t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8
80 if isOptional || isRepeated {
81 t = t.Elem()
82 }
Joe Tsaid8881392019-06-06 13:01:53 -070083 switch v := reflect.Zero(t).Interface().(type) {
84 case pref.Enum:
85 ed = v.Descriptor()
86 case enumV1:
87 ed = LegacyLoadEnumDesc(t)
88 case pref.ProtoMessage:
89 md = v.ProtoReflect().Descriptor()
90 case messageV1:
91 md = LegacyLoadMessageDesc(t)
92 }
93
94 // Derive basic field information from the struct tag.
95 var evs pref.EnumValueDescriptors
96 if ed != nil {
97 evs = ed.Values()
98 }
Damien Neilf1e905b2019-08-08 15:45:59 -070099 fd := ptag.Unmarshal(xi.Tag, t, evs).(*filedesc.Field)
Joe Tsai08e00302018-11-26 22:32:06 -0800100
101 // Construct a v2 ExtensionType.
Joe Tsaid8881392019-06-06 13:01:53 -0700102 xd := &filedesc.Extension{L2: new(filedesc.ExtensionL2)}
103 xd.L0.ParentFile = filedesc.SurrogateProto2
Damien Neilf1e905b2019-08-08 15:45:59 -0700104 xd.L0.FullName = pref.FullName(xi.Name)
105 xd.L1.Number = pref.FieldNumber(xi.Field)
Joe Tsaifd4c6052019-09-16 13:30:15 -0700106 xd.L1.Cardinality = fd.L1.Cardinality
Joe Tsaid8881392019-06-06 13:01:53 -0700107 xd.L1.Kind = fd.L1.Kind
108 xd.L2.IsPacked = fd.L1.IsPacked
109 xd.L2.Default = fd.L1.Default
Damien Neilf1e905b2019-08-08 15:45:59 -0700110 xd.L1.Extendee = Export{}.MessageDescriptorOf(xi.ExtendedType)
Joe Tsaid8881392019-06-06 13:01:53 -0700111 xd.L2.Enum = ed
112 xd.L2.Message = md
Joe Tsai945a1702019-07-20 14:57:56 -0700113
114 // Derive real extension field name for MessageSets.
115 if messageset.IsMessageSet(xd.L1.Extendee) && md.FullName() == xd.L0.FullName {
116 xd.L0.FullName = xd.L0.FullName.Append(messageset.ExtensionName)
117 }
118
Damien Neilf1e905b2019-08-08 15:45:59 -0700119 tt := reflect.TypeOf(xi.ExtensionType)
Damien Neil954bd922019-07-17 16:52:10 -0700120 if isOptional {
121 tt = tt.Elem()
Damien Neil954bd922019-07-17 16:52:10 -0700122 }
Damien Neilf1e905b2019-08-08 15:45:59 -0700123 xi.goType = tt
Joe Tsaifd4c6052019-09-16 13:30:15 -0700124 xi.desc = extensionTypeDescriptor{xd, xi}
Joe Tsai08e00302018-11-26 22:32:06 -0800125}