xref: /aosp_15_r20/external/golang-protobuf/reflect/protodesc/desc_init.go (revision 1c12ee1efe575feb122dbf939ff15148a3b3e8f2)
1*1c12ee1eSDan Willemsen// Copyright 2019 The Go Authors. All rights reserved.
2*1c12ee1eSDan Willemsen// Use of this source code is governed by a BSD-style
3*1c12ee1eSDan Willemsen// license that can be found in the LICENSE file.
4*1c12ee1eSDan Willemsen
5*1c12ee1eSDan Willemsenpackage protodesc
6*1c12ee1eSDan Willemsen
7*1c12ee1eSDan Willemsenimport (
8*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/internal/errors"
9*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/internal/filedesc"
10*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/internal/strs"
11*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/proto"
12*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/reflect/protoreflect"
13*1c12ee1eSDan Willemsen
14*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/types/descriptorpb"
15*1c12ee1eSDan Willemsen)
16*1c12ee1eSDan Willemsen
17*1c12ee1eSDan Willemsentype descsByName map[protoreflect.FullName]protoreflect.Descriptor
18*1c12ee1eSDan Willemsen
19*1c12ee1eSDan Willemsenfunc (r descsByName) initEnumDeclarations(eds []*descriptorpb.EnumDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (es []filedesc.Enum, err error) {
20*1c12ee1eSDan Willemsen	es = make([]filedesc.Enum, len(eds)) // allocate up-front to ensure stable pointers
21*1c12ee1eSDan Willemsen	for i, ed := range eds {
22*1c12ee1eSDan Willemsen		e := &es[i]
23*1c12ee1eSDan Willemsen		e.L2 = new(filedesc.EnumL2)
24*1c12ee1eSDan Willemsen		if e.L0, err = r.makeBase(e, parent, ed.GetName(), i, sb); err != nil {
25*1c12ee1eSDan Willemsen			return nil, err
26*1c12ee1eSDan Willemsen		}
27*1c12ee1eSDan Willemsen		if opts := ed.GetOptions(); opts != nil {
28*1c12ee1eSDan Willemsen			opts = proto.Clone(opts).(*descriptorpb.EnumOptions)
29*1c12ee1eSDan Willemsen			e.L2.Options = func() protoreflect.ProtoMessage { return opts }
30*1c12ee1eSDan Willemsen		}
31*1c12ee1eSDan Willemsen		for _, s := range ed.GetReservedName() {
32*1c12ee1eSDan Willemsen			e.L2.ReservedNames.List = append(e.L2.ReservedNames.List, protoreflect.Name(s))
33*1c12ee1eSDan Willemsen		}
34*1c12ee1eSDan Willemsen		for _, rr := range ed.GetReservedRange() {
35*1c12ee1eSDan Willemsen			e.L2.ReservedRanges.List = append(e.L2.ReservedRanges.List, [2]protoreflect.EnumNumber{
36*1c12ee1eSDan Willemsen				protoreflect.EnumNumber(rr.GetStart()),
37*1c12ee1eSDan Willemsen				protoreflect.EnumNumber(rr.GetEnd()),
38*1c12ee1eSDan Willemsen			})
39*1c12ee1eSDan Willemsen		}
40*1c12ee1eSDan Willemsen		if e.L2.Values.List, err = r.initEnumValuesFromDescriptorProto(ed.GetValue(), e, sb); err != nil {
41*1c12ee1eSDan Willemsen			return nil, err
42*1c12ee1eSDan Willemsen		}
43*1c12ee1eSDan Willemsen	}
44*1c12ee1eSDan Willemsen	return es, nil
45*1c12ee1eSDan Willemsen}
46*1c12ee1eSDan Willemsen
47*1c12ee1eSDan Willemsenfunc (r descsByName) initEnumValuesFromDescriptorProto(vds []*descriptorpb.EnumValueDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (vs []filedesc.EnumValue, err error) {
48*1c12ee1eSDan Willemsen	vs = make([]filedesc.EnumValue, len(vds)) // allocate up-front to ensure stable pointers
49*1c12ee1eSDan Willemsen	for i, vd := range vds {
50*1c12ee1eSDan Willemsen		v := &vs[i]
51*1c12ee1eSDan Willemsen		if v.L0, err = r.makeBase(v, parent, vd.GetName(), i, sb); err != nil {
52*1c12ee1eSDan Willemsen			return nil, err
53*1c12ee1eSDan Willemsen		}
54*1c12ee1eSDan Willemsen		if opts := vd.GetOptions(); opts != nil {
55*1c12ee1eSDan Willemsen			opts = proto.Clone(opts).(*descriptorpb.EnumValueOptions)
56*1c12ee1eSDan Willemsen			v.L1.Options = func() protoreflect.ProtoMessage { return opts }
57*1c12ee1eSDan Willemsen		}
58*1c12ee1eSDan Willemsen		v.L1.Number = protoreflect.EnumNumber(vd.GetNumber())
59*1c12ee1eSDan Willemsen	}
60*1c12ee1eSDan Willemsen	return vs, nil
61*1c12ee1eSDan Willemsen}
62*1c12ee1eSDan Willemsen
63*1c12ee1eSDan Willemsenfunc (r descsByName) initMessagesDeclarations(mds []*descriptorpb.DescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (ms []filedesc.Message, err error) {
64*1c12ee1eSDan Willemsen	ms = make([]filedesc.Message, len(mds)) // allocate up-front to ensure stable pointers
65*1c12ee1eSDan Willemsen	for i, md := range mds {
66*1c12ee1eSDan Willemsen		m := &ms[i]
67*1c12ee1eSDan Willemsen		m.L2 = new(filedesc.MessageL2)
68*1c12ee1eSDan Willemsen		if m.L0, err = r.makeBase(m, parent, md.GetName(), i, sb); err != nil {
69*1c12ee1eSDan Willemsen			return nil, err
70*1c12ee1eSDan Willemsen		}
71*1c12ee1eSDan Willemsen		if opts := md.GetOptions(); opts != nil {
72*1c12ee1eSDan Willemsen			opts = proto.Clone(opts).(*descriptorpb.MessageOptions)
73*1c12ee1eSDan Willemsen			m.L2.Options = func() protoreflect.ProtoMessage { return opts }
74*1c12ee1eSDan Willemsen			m.L1.IsMapEntry = opts.GetMapEntry()
75*1c12ee1eSDan Willemsen			m.L1.IsMessageSet = opts.GetMessageSetWireFormat()
76*1c12ee1eSDan Willemsen		}
77*1c12ee1eSDan Willemsen		for _, s := range md.GetReservedName() {
78*1c12ee1eSDan Willemsen			m.L2.ReservedNames.List = append(m.L2.ReservedNames.List, protoreflect.Name(s))
79*1c12ee1eSDan Willemsen		}
80*1c12ee1eSDan Willemsen		for _, rr := range md.GetReservedRange() {
81*1c12ee1eSDan Willemsen			m.L2.ReservedRanges.List = append(m.L2.ReservedRanges.List, [2]protoreflect.FieldNumber{
82*1c12ee1eSDan Willemsen				protoreflect.FieldNumber(rr.GetStart()),
83*1c12ee1eSDan Willemsen				protoreflect.FieldNumber(rr.GetEnd()),
84*1c12ee1eSDan Willemsen			})
85*1c12ee1eSDan Willemsen		}
86*1c12ee1eSDan Willemsen		for _, xr := range md.GetExtensionRange() {
87*1c12ee1eSDan Willemsen			m.L2.ExtensionRanges.List = append(m.L2.ExtensionRanges.List, [2]protoreflect.FieldNumber{
88*1c12ee1eSDan Willemsen				protoreflect.FieldNumber(xr.GetStart()),
89*1c12ee1eSDan Willemsen				protoreflect.FieldNumber(xr.GetEnd()),
90*1c12ee1eSDan Willemsen			})
91*1c12ee1eSDan Willemsen			var optsFunc func() protoreflect.ProtoMessage
92*1c12ee1eSDan Willemsen			if opts := xr.GetOptions(); opts != nil {
93*1c12ee1eSDan Willemsen				opts = proto.Clone(opts).(*descriptorpb.ExtensionRangeOptions)
94*1c12ee1eSDan Willemsen				optsFunc = func() protoreflect.ProtoMessage { return opts }
95*1c12ee1eSDan Willemsen			}
96*1c12ee1eSDan Willemsen			m.L2.ExtensionRangeOptions = append(m.L2.ExtensionRangeOptions, optsFunc)
97*1c12ee1eSDan Willemsen		}
98*1c12ee1eSDan Willemsen		if m.L2.Fields.List, err = r.initFieldsFromDescriptorProto(md.GetField(), m, sb); err != nil {
99*1c12ee1eSDan Willemsen			return nil, err
100*1c12ee1eSDan Willemsen		}
101*1c12ee1eSDan Willemsen		if m.L2.Oneofs.List, err = r.initOneofsFromDescriptorProto(md.GetOneofDecl(), m, sb); err != nil {
102*1c12ee1eSDan Willemsen			return nil, err
103*1c12ee1eSDan Willemsen		}
104*1c12ee1eSDan Willemsen		if m.L1.Enums.List, err = r.initEnumDeclarations(md.GetEnumType(), m, sb); err != nil {
105*1c12ee1eSDan Willemsen			return nil, err
106*1c12ee1eSDan Willemsen		}
107*1c12ee1eSDan Willemsen		if m.L1.Messages.List, err = r.initMessagesDeclarations(md.GetNestedType(), m, sb); err != nil {
108*1c12ee1eSDan Willemsen			return nil, err
109*1c12ee1eSDan Willemsen		}
110*1c12ee1eSDan Willemsen		if m.L1.Extensions.List, err = r.initExtensionDeclarations(md.GetExtension(), m, sb); err != nil {
111*1c12ee1eSDan Willemsen			return nil, err
112*1c12ee1eSDan Willemsen		}
113*1c12ee1eSDan Willemsen	}
114*1c12ee1eSDan Willemsen	return ms, nil
115*1c12ee1eSDan Willemsen}
116*1c12ee1eSDan Willemsen
117*1c12ee1eSDan Willemsenfunc (r descsByName) initFieldsFromDescriptorProto(fds []*descriptorpb.FieldDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (fs []filedesc.Field, err error) {
118*1c12ee1eSDan Willemsen	fs = make([]filedesc.Field, len(fds)) // allocate up-front to ensure stable pointers
119*1c12ee1eSDan Willemsen	for i, fd := range fds {
120*1c12ee1eSDan Willemsen		f := &fs[i]
121*1c12ee1eSDan Willemsen		if f.L0, err = r.makeBase(f, parent, fd.GetName(), i, sb); err != nil {
122*1c12ee1eSDan Willemsen			return nil, err
123*1c12ee1eSDan Willemsen		}
124*1c12ee1eSDan Willemsen		f.L1.IsProto3Optional = fd.GetProto3Optional()
125*1c12ee1eSDan Willemsen		if opts := fd.GetOptions(); opts != nil {
126*1c12ee1eSDan Willemsen			opts = proto.Clone(opts).(*descriptorpb.FieldOptions)
127*1c12ee1eSDan Willemsen			f.L1.Options = func() protoreflect.ProtoMessage { return opts }
128*1c12ee1eSDan Willemsen			f.L1.IsWeak = opts.GetWeak()
129*1c12ee1eSDan Willemsen			f.L1.HasPacked = opts.Packed != nil
130*1c12ee1eSDan Willemsen			f.L1.IsPacked = opts.GetPacked()
131*1c12ee1eSDan Willemsen		}
132*1c12ee1eSDan Willemsen		f.L1.Number = protoreflect.FieldNumber(fd.GetNumber())
133*1c12ee1eSDan Willemsen		f.L1.Cardinality = protoreflect.Cardinality(fd.GetLabel())
134*1c12ee1eSDan Willemsen		if fd.Type != nil {
135*1c12ee1eSDan Willemsen			f.L1.Kind = protoreflect.Kind(fd.GetType())
136*1c12ee1eSDan Willemsen		}
137*1c12ee1eSDan Willemsen		if fd.JsonName != nil {
138*1c12ee1eSDan Willemsen			f.L1.StringName.InitJSON(fd.GetJsonName())
139*1c12ee1eSDan Willemsen		}
140*1c12ee1eSDan Willemsen	}
141*1c12ee1eSDan Willemsen	return fs, nil
142*1c12ee1eSDan Willemsen}
143*1c12ee1eSDan Willemsen
144*1c12ee1eSDan Willemsenfunc (r descsByName) initOneofsFromDescriptorProto(ods []*descriptorpb.OneofDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (os []filedesc.Oneof, err error) {
145*1c12ee1eSDan Willemsen	os = make([]filedesc.Oneof, len(ods)) // allocate up-front to ensure stable pointers
146*1c12ee1eSDan Willemsen	for i, od := range ods {
147*1c12ee1eSDan Willemsen		o := &os[i]
148*1c12ee1eSDan Willemsen		if o.L0, err = r.makeBase(o, parent, od.GetName(), i, sb); err != nil {
149*1c12ee1eSDan Willemsen			return nil, err
150*1c12ee1eSDan Willemsen		}
151*1c12ee1eSDan Willemsen		if opts := od.GetOptions(); opts != nil {
152*1c12ee1eSDan Willemsen			opts = proto.Clone(opts).(*descriptorpb.OneofOptions)
153*1c12ee1eSDan Willemsen			o.L1.Options = func() protoreflect.ProtoMessage { return opts }
154*1c12ee1eSDan Willemsen		}
155*1c12ee1eSDan Willemsen	}
156*1c12ee1eSDan Willemsen	return os, nil
157*1c12ee1eSDan Willemsen}
158*1c12ee1eSDan Willemsen
159*1c12ee1eSDan Willemsenfunc (r descsByName) initExtensionDeclarations(xds []*descriptorpb.FieldDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (xs []filedesc.Extension, err error) {
160*1c12ee1eSDan Willemsen	xs = make([]filedesc.Extension, len(xds)) // allocate up-front to ensure stable pointers
161*1c12ee1eSDan Willemsen	for i, xd := range xds {
162*1c12ee1eSDan Willemsen		x := &xs[i]
163*1c12ee1eSDan Willemsen		x.L2 = new(filedesc.ExtensionL2)
164*1c12ee1eSDan Willemsen		if x.L0, err = r.makeBase(x, parent, xd.GetName(), i, sb); err != nil {
165*1c12ee1eSDan Willemsen			return nil, err
166*1c12ee1eSDan Willemsen		}
167*1c12ee1eSDan Willemsen		if opts := xd.GetOptions(); opts != nil {
168*1c12ee1eSDan Willemsen			opts = proto.Clone(opts).(*descriptorpb.FieldOptions)
169*1c12ee1eSDan Willemsen			x.L2.Options = func() protoreflect.ProtoMessage { return opts }
170*1c12ee1eSDan Willemsen			x.L2.IsPacked = opts.GetPacked()
171*1c12ee1eSDan Willemsen		}
172*1c12ee1eSDan Willemsen		x.L1.Number = protoreflect.FieldNumber(xd.GetNumber())
173*1c12ee1eSDan Willemsen		x.L1.Cardinality = protoreflect.Cardinality(xd.GetLabel())
174*1c12ee1eSDan Willemsen		if xd.Type != nil {
175*1c12ee1eSDan Willemsen			x.L1.Kind = protoreflect.Kind(xd.GetType())
176*1c12ee1eSDan Willemsen		}
177*1c12ee1eSDan Willemsen		if xd.JsonName != nil {
178*1c12ee1eSDan Willemsen			x.L2.StringName.InitJSON(xd.GetJsonName())
179*1c12ee1eSDan Willemsen		}
180*1c12ee1eSDan Willemsen	}
181*1c12ee1eSDan Willemsen	return xs, nil
182*1c12ee1eSDan Willemsen}
183*1c12ee1eSDan Willemsen
184*1c12ee1eSDan Willemsenfunc (r descsByName) initServiceDeclarations(sds []*descriptorpb.ServiceDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (ss []filedesc.Service, err error) {
185*1c12ee1eSDan Willemsen	ss = make([]filedesc.Service, len(sds)) // allocate up-front to ensure stable pointers
186*1c12ee1eSDan Willemsen	for i, sd := range sds {
187*1c12ee1eSDan Willemsen		s := &ss[i]
188*1c12ee1eSDan Willemsen		s.L2 = new(filedesc.ServiceL2)
189*1c12ee1eSDan Willemsen		if s.L0, err = r.makeBase(s, parent, sd.GetName(), i, sb); err != nil {
190*1c12ee1eSDan Willemsen			return nil, err
191*1c12ee1eSDan Willemsen		}
192*1c12ee1eSDan Willemsen		if opts := sd.GetOptions(); opts != nil {
193*1c12ee1eSDan Willemsen			opts = proto.Clone(opts).(*descriptorpb.ServiceOptions)
194*1c12ee1eSDan Willemsen			s.L2.Options = func() protoreflect.ProtoMessage { return opts }
195*1c12ee1eSDan Willemsen		}
196*1c12ee1eSDan Willemsen		if s.L2.Methods.List, err = r.initMethodsFromDescriptorProto(sd.GetMethod(), s, sb); err != nil {
197*1c12ee1eSDan Willemsen			return nil, err
198*1c12ee1eSDan Willemsen		}
199*1c12ee1eSDan Willemsen	}
200*1c12ee1eSDan Willemsen	return ss, nil
201*1c12ee1eSDan Willemsen}
202*1c12ee1eSDan Willemsen
203*1c12ee1eSDan Willemsenfunc (r descsByName) initMethodsFromDescriptorProto(mds []*descriptorpb.MethodDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (ms []filedesc.Method, err error) {
204*1c12ee1eSDan Willemsen	ms = make([]filedesc.Method, len(mds)) // allocate up-front to ensure stable pointers
205*1c12ee1eSDan Willemsen	for i, md := range mds {
206*1c12ee1eSDan Willemsen		m := &ms[i]
207*1c12ee1eSDan Willemsen		if m.L0, err = r.makeBase(m, parent, md.GetName(), i, sb); err != nil {
208*1c12ee1eSDan Willemsen			return nil, err
209*1c12ee1eSDan Willemsen		}
210*1c12ee1eSDan Willemsen		if opts := md.GetOptions(); opts != nil {
211*1c12ee1eSDan Willemsen			opts = proto.Clone(opts).(*descriptorpb.MethodOptions)
212*1c12ee1eSDan Willemsen			m.L1.Options = func() protoreflect.ProtoMessage { return opts }
213*1c12ee1eSDan Willemsen		}
214*1c12ee1eSDan Willemsen		m.L1.IsStreamingClient = md.GetClientStreaming()
215*1c12ee1eSDan Willemsen		m.L1.IsStreamingServer = md.GetServerStreaming()
216*1c12ee1eSDan Willemsen	}
217*1c12ee1eSDan Willemsen	return ms, nil
218*1c12ee1eSDan Willemsen}
219*1c12ee1eSDan Willemsen
220*1c12ee1eSDan Willemsenfunc (r descsByName) makeBase(child, parent protoreflect.Descriptor, name string, idx int, sb *strs.Builder) (filedesc.BaseL0, error) {
221*1c12ee1eSDan Willemsen	if !protoreflect.Name(name).IsValid() {
222*1c12ee1eSDan Willemsen		return filedesc.BaseL0{}, errors.New("descriptor %q has an invalid nested name: %q", parent.FullName(), name)
223*1c12ee1eSDan Willemsen	}
224*1c12ee1eSDan Willemsen
225*1c12ee1eSDan Willemsen	// Derive the full name of the child.
226*1c12ee1eSDan Willemsen	// Note that enum values are a sibling to the enum parent in the namespace.
227*1c12ee1eSDan Willemsen	var fullName protoreflect.FullName
228*1c12ee1eSDan Willemsen	if _, ok := parent.(protoreflect.EnumDescriptor); ok {
229*1c12ee1eSDan Willemsen		fullName = sb.AppendFullName(parent.FullName().Parent(), protoreflect.Name(name))
230*1c12ee1eSDan Willemsen	} else {
231*1c12ee1eSDan Willemsen		fullName = sb.AppendFullName(parent.FullName(), protoreflect.Name(name))
232*1c12ee1eSDan Willemsen	}
233*1c12ee1eSDan Willemsen	if _, ok := r[fullName]; ok {
234*1c12ee1eSDan Willemsen		return filedesc.BaseL0{}, errors.New("descriptor %q already declared", fullName)
235*1c12ee1eSDan Willemsen	}
236*1c12ee1eSDan Willemsen	r[fullName] = child
237*1c12ee1eSDan Willemsen
238*1c12ee1eSDan Willemsen	// TODO: Verify that the full name does not already exist in the resolver?
239*1c12ee1eSDan Willemsen	// This is not as critical since most usages of NewFile will register
240*1c12ee1eSDan Willemsen	// the created file back into the registry, which will perform this check.
241*1c12ee1eSDan Willemsen
242*1c12ee1eSDan Willemsen	return filedesc.BaseL0{
243*1c12ee1eSDan Willemsen		FullName:   fullName,
244*1c12ee1eSDan Willemsen		ParentFile: parent.ParentFile().(*filedesc.File),
245*1c12ee1eSDan Willemsen		Parent:     parent,
246*1c12ee1eSDan Willemsen		Index:      idx,
247*1c12ee1eSDan Willemsen	}, nil
248*1c12ee1eSDan Willemsen}
249