internal FieldDescriptor(FieldDescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int index, string propertyName, Extension extension) : base(file, file.ComputeFullName(parent, proto.Name), index) { Proto = proto; if (proto.Type != 0) { fieldType = GetFieldTypeFromProtoType(proto.Type); } if (FieldNumber <= 0) { throw new DescriptorValidationException(this, "Field numbers must be positive integers."); } ContainingType = parent; if (proto.HasOneofIndex) { if (proto.OneofIndex < 0 || proto.OneofIndex >= parent.Proto.OneofDecl.Count) { throw new DescriptorValidationException(this, $"FieldDescriptorProto.oneof_index is out of range for type {parent.Name}"); } ContainingOneof = parent.Oneofs[proto.OneofIndex]; } file.DescriptorPool.AddSymbol(this); // We can't create the accessor until we've cross-linked, unfortunately, as we // may not know whether the type of the field is a map or not. Remember the property name // for later. // We could trust the generated code and check whether the type of the property is // a MapField, but that feels a tad nasty. this.propertyName = propertyName; Extension = extension; JsonName = Proto.JsonName == "" ? JsonFormatter.ToJsonName(Proto.Name) : Proto.JsonName; }
internal ServiceDescriptor(ServiceDescriptorProto proto, FileDescriptor file, int index) : base(file, file.ComputeFullName(null, proto.Name), index) { this.proto = proto; methods = DescriptorUtil.ConvertAndMakeReadOnly(proto.Method, (method, i) => new MethodDescriptor(method, file, this, i)); file.DescriptorPool.AddSymbol(this); }
internal MessageDescriptor(DescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int typeIndex, GeneratedClrTypeInfo generatedCodeInfo) : base(file, file.ComputeFullName(parent, proto.Name), typeIndex) { Proto = proto; Parser = generatedCodeInfo?.Parser; ClrType = generatedCodeInfo?.ClrType; ContainingType = parent; // If generatedCodeInfo is null, we just won't generate an accessor for any fields. Oneofs = DescriptorUtil.ConvertAndMakeReadOnly( proto.OneofDecl, (oneof, index) => new OneofDescriptor(oneof, file, this, index, generatedCodeInfo?.OneofNames[index])); int syntheticOneofCount = 0; foreach (var oneof in Oneofs) { if (oneof.IsSynthetic) { syntheticOneofCount++; } else if (syntheticOneofCount != 0) { throw new ArgumentException("All synthetic oneofs should come after real oneofs"); } } RealOneofCount = Oneofs.Count - syntheticOneofCount; NestedTypes = DescriptorUtil.ConvertAndMakeReadOnly( proto.NestedType, (type, index) => new MessageDescriptor(type, file, this, index, generatedCodeInfo?.NestedTypes[index])); EnumTypes = DescriptorUtil.ConvertAndMakeReadOnly( proto.EnumType, (type, index) => new EnumDescriptor(type, file, this, index, generatedCodeInfo?.NestedEnums[index])); Extensions = new ExtensionCollection(this, generatedCodeInfo?.Extensions); fieldsInDeclarationOrder = DescriptorUtil.ConvertAndMakeReadOnly( proto.Field, (field, index) => new FieldDescriptor(field, file, this, index, generatedCodeInfo?.PropertyNames[index], null)); fieldsInNumberOrder = new ReadOnlyCollection <FieldDescriptor>(fieldsInDeclarationOrder.OrderBy(field => field.FieldNumber).ToArray()); // TODO: Use field => field.Proto.JsonName when we're confident it's appropriate. (And then use it in the formatter, too.) jsonFieldMap = CreateJsonFieldMap(fieldsInNumberOrder); file.DescriptorPool.AddSymbol(this); Fields = new FieldCollection(this); }
internal OneofDescriptor(OneofDescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int index, string clrName) : base(file, file.ComputeFullName(parent, proto.Name), index) { this.proto = proto; containingType = parent; file.DescriptorPool.AddSymbol(this); // It's useful to determine whether or not this is a synthetic oneof before cross-linking. That means // diving into the proto directly rather than using FieldDescriptor, but that's okay. var firstFieldInOneof = parent.Proto.Field.FirstOrDefault(fieldProto => fieldProto.HasOneofIndex && fieldProto.OneofIndex == index); IsSynthetic = firstFieldInOneof?.Proto3Optional ?? false; accessor = CreateAccessor(clrName); }
internal EnumDescriptor(EnumDescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int index, Type clrType) : base(file, file.ComputeFullName(parent, proto.Name), index) { this.proto = proto; this.clrType = clrType; containingType = parent; if (proto.Value.Count == 0) { // We cannot allow enums with no values because this would mean there // would be no valid default value for fields of this type. throw new DescriptorValidationException(this, "Enums must contain at least one value."); } values = DescriptorUtil.ConvertAndMakeReadOnly(proto.Value, (value, i) => new EnumValueDescriptor(value, file, this, i)); File.DescriptorPool.AddSymbol(this); }