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