| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419 | 
							- using System;
 
- using System.Collections.Generic;
 
- using System.Reflection;
 
- using Google.ProtocolBuffers.Collections;
 
- using Google.ProtocolBuffers.DescriptorProtos;
 
- using System.Collections.ObjectModel;
 
- namespace Google.ProtocolBuffers.Descriptors {
 
-   public class FieldDescriptor : IndexedDescriptorBase<FieldDescriptorProto, FieldOptions>, IComparable<FieldDescriptor> {
 
-     private readonly MessageDescriptor extensionScope;
 
-     private EnumDescriptor enumType;
 
-     private MessageDescriptor messageType;
 
-     private MessageDescriptor containingType;
 
-     private object defaultValue;
 
-     private FieldType fieldType;
 
-     private MappedType mappedType;
 
-     internal FieldDescriptor(FieldDescriptorProto proto, FileDescriptor file,
 
-         MessageDescriptor parent, int index, bool isExtension) 
 
-         : base(proto, file, ComputeFullName(file, parent, proto.Name), index) {
 
-       
 
-       if (proto.HasType) {
 
-         fieldType = GetFieldTypeFromProtoType(proto.Type);
 
-         mappedType = FieldTypeToMappedTypeMap[fieldType];
 
-       }
 
-       
 
-       if (FieldNumber <= 0) {
 
-         throw new DescriptorValidationException(this,
 
-           "Field numbers must be positive integers.");
 
-       }
 
-       if (isExtension) {
 
-         if (!proto.HasExtendee) {
 
-           throw new DescriptorValidationException(this,
 
-               "FieldDescriptorProto.Extendee not set for extension field.");
 
-         }
 
-         containingType = null;  // Will be filled in when cross-linking
 
-         if (parent != null) {
 
-           extensionScope = parent;
 
-         } else {
 
-           extensionScope = null;
 
-         }
 
-       } else {
 
-         if (proto.HasExtendee) {
 
-           throw new DescriptorValidationException(this,
 
-               "FieldDescriptorProto.Extendee set for non-extension field.");
 
-         }
 
-         containingType = parent;
 
-         extensionScope = null;
 
-       }
 
-       file.DescriptorPool.AddSymbol(this);
 
-     }
 
-     /// <summary>
 
-     /// Maps a field type as included in the .proto file to a FieldType.
 
-     /// </summary>
 
-     private static FieldType GetFieldTypeFromProtoType(FieldDescriptorProto.Types.Type type) {
 
-       switch (type) {
 
-         case FieldDescriptorProto.Types.Type.TYPE_DOUBLE:   return FieldType.Double;
 
-         case FieldDescriptorProto.Types.Type.TYPE_FLOAT:    return FieldType.Float;
 
-         case FieldDescriptorProto.Types.Type.TYPE_INT64:    return FieldType.Int64;
 
-         case FieldDescriptorProto.Types.Type.TYPE_UINT64:   return FieldType.UInt64;
 
-         case FieldDescriptorProto.Types.Type.TYPE_INT32:    return FieldType.Int32;
 
-         case FieldDescriptorProto.Types.Type.TYPE_FIXED64:  return FieldType.Fixed64;
 
-         case FieldDescriptorProto.Types.Type.TYPE_FIXED32:  return FieldType.Fixed32;
 
-         case FieldDescriptorProto.Types.Type.TYPE_BOOL:     return FieldType.Bool;
 
-         case FieldDescriptorProto.Types.Type.TYPE_STRING:   return FieldType.String;
 
-         case FieldDescriptorProto.Types.Type.TYPE_GROUP:    return FieldType.Group;
 
-         case FieldDescriptorProto.Types.Type.TYPE_MESSAGE:  return FieldType.Message;
 
-         case FieldDescriptorProto.Types.Type.TYPE_BYTES:    return FieldType.Bytes;
 
-         case FieldDescriptorProto.Types.Type.TYPE_UINT32:   return FieldType.UInt32;
 
-         case FieldDescriptorProto.Types.Type.TYPE_ENUM:     return FieldType.Enum;
 
-         case FieldDescriptorProto.Types.Type.TYPE_SFIXED32: return FieldType.SFixed32;
 
-         case FieldDescriptorProto.Types.Type.TYPE_SFIXED64: return FieldType.SFixed64;
 
-         case FieldDescriptorProto.Types.Type.TYPE_SINT32:   return FieldType.SInt32;
 
-         case FieldDescriptorProto.Types.Type.TYPE_SINT64:   return FieldType.SInt64;
 
-         default:
 
-           throw new ArgumentException("Invalid type specified");
 
-       }
 
-     }
 
-     /// <summary>
 
-     /// Returns the default value for a mapped type.
 
-     /// </summary>
 
-     private static object GetDefaultValueForMappedType(MappedType type) {
 
-       switch (type) {
 
-         case MappedType.Int32: return 0;
 
-         case MappedType.Int64: return (long) 0;
 
-         case MappedType.UInt32: return (uint) 0;
 
-         case MappedType.UInt64: return (ulong) 0;
 
-         case MappedType.Single: return (float) 0;
 
-         case MappedType.Double: return (double) 0;
 
-         case MappedType.Boolean: return false;
 
-         case MappedType.String: return "";
 
-         case MappedType.ByteString: return ByteString.Empty;
 
-         case MappedType.Message: return null;
 
-         case MappedType.Enum: return null;
 
-         default:
 
-             throw new ArgumentException("Invalid type specified");
 
-       }
 
-     }
 
-     public bool IsRequired {
 
-       get { return Proto.Label == FieldDescriptorProto.Types.Label.LABEL_REQUIRED; }
 
-     }
 
-     public bool IsOptional {
 
-       get { return Proto.Label == FieldDescriptorProto.Types.Label.LABEL_OPTIONAL; }
 
-     }
 
-     public bool IsRepeated {
 
-       get { return Proto.Label == FieldDescriptorProto.Types.Label.LABEL_REPEATED; }
 
-     }
 
-     /// <valule>
 
-     /// Indicates whether or not the field had an explicitly-defined default value.
 
-     /// </value>
 
-     public bool HasDefaultValue {
 
-       get { return Proto.HasDefaultValue; }
 
-     }
 
-     /// <value>
 
-     /// The field's default value. Valid for all types except messages
 
-     /// and groups. For all other types, the object returned is of the
 
-     /// same class that would be returned by IMessage[this].
 
-     /// For repeated fields this will always be an empty immutable list compatible with IList[object].
 
-     /// For message fields it will always be null. For singular values, it will depend on the descriptor.
 
-     /// </value>
 
-     public object DefaultValue {
 
-       get {
 
-         if (MappedType == MappedType.Message) {
 
-           throw new InvalidOperationException("FieldDescriptor.DefaultValue called on an embedded message field.");
 
-         }
 
-         return defaultValue;
 
-       }
 
-     }
 
-     /// <value>
 
-     /// Indicates whether or not this field is an extension.
 
-     /// </value>
 
-     public bool IsExtension {
 
-       get { return Proto.HasExtendee; }
 
-     }
 
-     /*
 
-      * Get the field's containing type. For extensions, this is the type being
 
-      * extended, not the location where the extension was defined.  See
 
-      * {@link #getExtensionScope()}.
 
-      */
 
-     /// <summary>
 
-     /// Get the field's containing type. For extensions, this is the type being
 
-     /// extended, not the location where the extension was defined. See
 
-     /// <see cref="ExtensionScope" />.
 
-     /// </summary>
 
-     public MessageDescriptor ContainingType {
 
-       get { return containingType; }
 
-     }
 
-     
 
-     /// <summary>
 
-     /// For extensions defined nested within message types, gets
 
-     /// the outer type. Not valid for non-extension fields.
 
-     /// </summary>
 
-     /// <example>
 
-     /// <code>
 
-     /// message Foo {
 
-     ///   extensions 1000 to max;
 
-     /// }
 
-     /// extend Foo {
 
-     ///   optional int32 baz = 1234;
 
-     /// }
 
-     /// message Bar {
 
-     ///   extend Foo {
 
-     ///     optional int32 qux = 4321;
 
-     ///   }
 
-     /// }
 
-     /// </code>
 
-     /// The containing type for both <c>baz</c> and <c>qux</c> is <c>Foo</c>.
 
-     /// However, the extension scope for <c>baz</c> is <c>null</c> while
 
-     /// the extension scope for <c>qux</c> is <c>Bar</c>.
 
-     /// </example>
 
-     public MessageDescriptor ExtensionScope {
 
-       get {
 
-         if (!IsExtension) {
 
-           throw new InvalidOperationException("This field is not an extension.");
 
-         }
 
-         return extensionScope;
 
-       }
 
-     }
 
-     public MappedType MappedType {
 
-       get { return mappedType; }
 
-     }
 
-     public FieldType FieldType {
 
-       get { return fieldType; }
 
-     }
 
-     public int FieldNumber {
 
-       get { return Proto.Number; }
 
-     }
 
-     /// <summary>
 
-     /// Compares this descriptor with another one, ordering in "canonical" order
 
-     /// which simply means ascending order by field number. <paramref name="other"/>
 
-     /// must be a field of the same type, i.e. the <see cref="ContainingType"/> of
 
-     /// both fields must be the same.
 
-     /// </summary>
 
-     public int CompareTo(FieldDescriptor other) {
 
-       if (other.containingType != containingType) {
 
-         throw new ArgumentException("FieldDescriptors can only be compared to other FieldDescriptors " +
 
-           "for fields of the same message type.");
 
-       }
 
-       return FieldNumber - other.FieldNumber;
 
-     }
 
-     
 
-     /// <summary>
 
-     /// For enum fields, returns the field's type.
 
-     /// </summary>
 
-     public EnumDescriptor EnumType {
 
-       get {
 
-         if (MappedType != MappedType.Enum) {
 
-           throw new InvalidOperationException("EnumType is only valid for enum fields.");
 
-         }
 
-         return enumType;
 
-       }
 
-     }
 
-     /// <summary>
 
-     /// For embedded message and group fields, returns the field's type.
 
-     /// </summary>
 
-     public MessageDescriptor MessageType {
 
-       get {
 
-         if (MappedType != MappedType.Message) {
 
-           throw new InvalidOperationException("MessageType is only valid for enum fields.");
 
-         }
 
-         return messageType;
 
-       }
 
-     }
 
-     /// <summary>
 
-     /// Immutable mapping from field type to mapped type. Built using the attributes on
 
-     /// FieldType values.
 
-     /// </summary>
 
-     public static readonly IDictionary<FieldType, MappedType> FieldTypeToMappedTypeMap = MapFieldTypes();
 
-     private static IDictionary<FieldType, MappedType> MapFieldTypes() {
 
-       var map = new Dictionary<FieldType, MappedType>();
 
-       foreach (FieldInfo field in typeof(FieldType).GetFields(BindingFlags.Static | BindingFlags.Public)) {
 
-         FieldType fieldType = (FieldType)field.GetValue(null);
 
-         FieldMappingAttribute mapping = (FieldMappingAttribute)field.GetCustomAttributes(typeof(FieldMappingAttribute), false)[0];
 
-         map[fieldType] = mapping.MappedType;
 
-       }
 
-       return Dictionaries.AsReadOnly(map);
 
-     }
 
-     /// <summary>
 
-     /// Look up and cross-link all field types etc.
 
-     /// </summary>
 
-     internal void CrossLink() {
 
-       if (Proto.HasExtendee) {
 
-         IDescriptor extendee = File.DescriptorPool.LookupSymbol(Proto.Extendee, this);
 
-         if (!(extendee is MessageDescriptor)) {
 
-           throw new DescriptorValidationException(this, "\"" + Proto.Extendee + "\" is not a message type.");
 
-         }
 
-         containingType = (MessageDescriptor) extendee;
 
-         if (!containingType.IsExtensionNumber(FieldNumber)) {
 
-           throw new DescriptorValidationException(this,
 
-               "\"" + containingType.FullName + "\" does not declare " + FieldNumber + " as an extension number.");
 
-         }
 
-       }
 
-       if (Proto.HasTypeName) {
 
-         IDescriptor typeDescriptor =
 
-           File.DescriptorPool.LookupSymbol(Proto.TypeName, this);
 
-         if (!Proto.HasType) {
 
-           // Choose field type based on symbol.
 
-           if (typeDescriptor is MessageDescriptor) {
 
-             fieldType = FieldType.Message;
 
-             mappedType = MappedType.Message;
 
-           } else if (typeDescriptor is EnumDescriptor) {
 
-             fieldType = FieldType.Enum;
 
-             mappedType = MappedType.Enum;
 
-           } else {
 
-             throw new DescriptorValidationException(this, "\"" + Proto.TypeName + "\" is not a type.");
 
-           }
 
-         }
 
-         if (MappedType == MappedType.Message) {
 
-           if (!(typeDescriptor is MessageDescriptor)) {
 
-             throw new DescriptorValidationException(this, "\"" + Proto.TypeName + "\" is not a message type.");
 
-           }
 
-           messageType = (MessageDescriptor) typeDescriptor;
 
-           if (Proto.HasDefaultValue) {
 
-             throw new DescriptorValidationException(this, "Messages can't have default values.");
 
-           }
 
-         } else if (MappedType == Descriptors.MappedType.Enum) {
 
-           if (!(typeDescriptor is EnumDescriptor)) {
 
-             throw new DescriptorValidationException(this, "\"" + Proto.TypeName + "\" is not an enum type.");
 
-           }
 
-           enumType = (EnumDescriptor)typeDescriptor;
 
-         } else {
 
-           throw new DescriptorValidationException(this, "Field with primitive type has type_name.");
 
-         }
 
-       } else {
 
-         if (MappedType == MappedType.Message || MappedType == MappedType.Enum) {
 
-           throw new DescriptorValidationException(this, "Field with message or enum type missing type_name.");
 
-         }
 
-       }
 
-       // We don't attempt to parse the default value until here because for
 
-       // enums we need the enum type's descriptor.
 
-       if (Proto.HasDefaultValue) {
 
-         if (IsRepeated) {
 
-           throw new DescriptorValidationException(this, "Repeated fields cannot have default values.");
 
-         }
 
-         try {
 
-           switch (FieldType) {
 
-             case FieldType.Int32:
 
-             case FieldType.SInt32:
 
-             case FieldType.SFixed32:
 
-               defaultValue = TextFormat.ParseInt32(Proto.DefaultValue);
 
-               break;
 
-             case FieldType.UInt32:
 
-             case FieldType.Fixed32:
 
-               defaultValue = TextFormat.ParseUInt32(Proto.DefaultValue);
 
-               break;
 
-             case FieldType.Int64:
 
-             case FieldType.SInt64:
 
-             case FieldType.SFixed64:
 
-               defaultValue = TextFormat.ParseInt64(Proto.DefaultValue);
 
-               break;
 
-             case FieldType.UInt64:
 
-             case FieldType.Fixed64:
 
-               defaultValue = TextFormat.ParseUInt64(Proto.DefaultValue);
 
-               break;
 
-             case FieldType.Float:
 
-               defaultValue = float.Parse(Proto.DefaultValue);
 
-               break;
 
-             case FieldType.Double:
 
-               defaultValue = double.Parse(Proto.DefaultValue);
 
-               break;
 
-             case FieldType.Bool:
 
-               if (Proto.DefaultValue == "true") {
 
-                 defaultValue = true;
 
-               } else if (Proto.DefaultValue == "false") {
 
-                 defaultValue = false;
 
-               } else {
 
-                 throw new FormatException("Boolean values must be \"true\" or \"false\"");
 
-               }
 
-               break;
 
-             case FieldType.String:
 
-               defaultValue = Proto.DefaultValue;
 
-               break;
 
-             case FieldType.Bytes:
 
-               try {
 
-                 defaultValue = TextFormat.UnescapeBytes(Proto.DefaultValue);
 
-               } catch (FormatException e) {
 
-                 throw new DescriptorValidationException(this, "Couldn't parse default value: " + e.Message);
 
-               }
 
-               break;
 
-             case FieldType.Enum:
 
-               defaultValue = enumType.FindValueByName(Proto.DefaultValue);
 
-               if (defaultValue == null) {
 
-                 throw new DescriptorValidationException(this, "Unknown enum default value: \"" + Proto.DefaultValue + "\"");
 
-               }
 
-               break;
 
-             case FieldType.Message:
 
-             case FieldType.Group:
 
-               throw new DescriptorValidationException(this, "Message type had default value.");
 
-           }
 
-         } catch (FormatException e) {
 
-           DescriptorValidationException validationException =
 
-               new DescriptorValidationException(this, "Could not parse default value: \"" + Proto.DefaultValue + "\"", e);
 
-           throw validationException;
 
-         }
 
-       } else {
 
-         // Determine the default default for this field.
 
-         if (IsRepeated) {
 
-           defaultValue = Lists<object>.Empty;
 
-         } else {
 
-           switch (MappedType) {
 
-             case MappedType.Enum:
 
-               // We guarantee elsewhere that an enum type always has at least
 
-               // one possible value.
 
-               defaultValue = enumType.Values[0];
 
-               break;
 
-             case MappedType.Message:
 
-               defaultValue = null;
 
-               break;
 
-             default:
 
-               defaultValue = GetDefaultValueForMappedType(MappedType);
 
-               break;
 
-           }
 
-         }
 
-       }
 
-       if (!IsExtension) {
 
-         File.DescriptorPool.AddFieldByNumber(this);
 
-       }
 
-       if (containingType != null && containingType.Options.MessageSetWireFormat) {
 
-         if (IsExtension) {
 
-           if (!IsOptional || FieldType != FieldType.Message) {
 
-             throw new DescriptorValidationException(this, "Extensions of MessageSets must be optional messages.");
 
-           }
 
-         } else {
 
-           throw new DescriptorValidationException(this, "MessageSets cannot have fields, only extensions.");
 
-         }
 
-       }
 
-     }
 
-   }
 
- }
 
 
  |