| 
					
				 | 
			
			
				@@ -5,43 +5,215 @@ using Google.ProtocolBuffers.Collections; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 using Google.ProtocolBuffers.DescriptorProtos; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 namespace Google.ProtocolBuffers.Descriptors { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  public class FieldDescriptor : IndexedDescriptorBase<FieldDescriptorProto, FieldOptions> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  public class FieldDescriptor : IndexedDescriptorBase<FieldDescriptorProto, FieldOptions>, IComparable<FieldDescriptor> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    private readonly EnumDescriptor enumType; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    private readonly MessageDescriptor parent; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    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, index) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      enumType = null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      this.parent = parent; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    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); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        //type = proto.Type; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      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; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      set; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      get { return Proto.Label == FieldDescriptorProto.Types.Label.LABEL_REQUIRED; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public bool IsOptional { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      get { return Proto.Label == FieldDescriptorProto.Types.Label.LABEL_OPTIONAL; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    public MappedType MappedType { get; set; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public bool IsRepeated { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      get { return Proto.Label == FieldDescriptorProto.Types.Label.LABEL_REPEATED; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    public bool IsRepeated { get; set; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// <valule> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// Indicates whether or not the field had an explicitly-defined default value. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// </value> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public bool HasDefaultValue { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      get { return Proto.HasDefaultValue; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    public FieldType FieldType { get; set; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    public int FieldNumber { get; set; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// <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 list. 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; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    public bool IsExtension { get; set; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// <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 parent; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      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 bool IsOptional { get; set; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public MappedType MappedType { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      get { return mappedType; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    public MessageDescriptor MessageType { get; set; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public FieldType FieldType { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      get { return fieldType; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    public MessageDescriptor ExtensionScope { get; set; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    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. 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -53,15 +225,18 @@ namespace Google.ProtocolBuffers.Descriptors { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return enumType; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    }    
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /// <summary> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    /// The default value for this field. For repeated fields 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    /// this will always be an empty list. For message fields it will 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    /// always be null. For singular values, it will depend on the descriptor. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /// For embedded message and group fields, returns the field's type. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /// </summary> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    public object DefaultValue { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      get { throw new NotImplementedException(); } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public MessageDescriptor MessageType { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      get { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (MappedType != MappedType.Message) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          throw new InvalidOperationException("MessageType is only valid for enum fields."); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return messageType; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /// <summary> 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -70,6 +245,7 @@ namespace Google.ProtocolBuffers.Descriptors { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /// </summary> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     public static readonly IDictionary<FieldType, MappedType> FieldTypeToWireFormatMap = MapFieldTypes(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     private static IDictionary<FieldType, MappedType> MapFieldTypes() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       var map = new Dictionary<FieldType, MappedType>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       foreach (FieldInfo field in typeof(FieldType).GetFields(BindingFlags.Static | BindingFlags.Public)) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -79,5 +255,161 @@ namespace Google.ProtocolBuffers.Descriptors { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       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 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          // TODO(jonskeet): Check signage for Int32 and Int64. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          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: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              defaultValue = bool.Parse(Proto.DefaultValue); // TODO(jonskeet): Check this will work 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              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) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          // FIXME(jonskeet): Find out the correct list type and use that instead. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          defaultValue = new List<object>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 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."); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 |