Commit 00b0af08 authored by Jon Skeet's avatar Jon Skeet

Fix default instance behaviour for repeated types

parent 4f435a50
...@@ -3,6 +3,7 @@ using System.Collections.Generic; ...@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using Google.ProtocolBuffers.Collections; using Google.ProtocolBuffers.Collections;
using Google.ProtocolBuffers.DescriptorProtos; using Google.ProtocolBuffers.DescriptorProtos;
using System.Collections.ObjectModel;
namespace Google.ProtocolBuffers.Descriptors { namespace Google.ProtocolBuffers.Descriptors {
public class FieldDescriptor : IndexedDescriptorBase<FieldDescriptorProto, FieldOptions>, IComparable<FieldDescriptor> { public class FieldDescriptor : IndexedDescriptorBase<FieldDescriptorProto, FieldOptions>, IComparable<FieldDescriptor> {
...@@ -124,8 +125,8 @@ namespace Google.ProtocolBuffers.Descriptors { ...@@ -124,8 +125,8 @@ namespace Google.ProtocolBuffers.Descriptors {
/// The field's default value. Valid for all types except messages /// The field's default value. Valid for all types except messages
/// and groups. For all other types, the object returned is of the /// and groups. For all other types, the object returned is of the
/// same class that would be returned by IMessage[this]. /// same class that would be returned by IMessage[this].
/// For repeated fields this will always be an empty list. For message fields it will /// For repeated fields this will always be an empty immutable list compatible with IList[object].
/// always be null. For singular values, it will depend on the descriptor. /// For message fields it will always be null. For singular values, it will depend on the descriptor.
/// </value> /// </value>
public object DefaultValue { public object DefaultValue {
get { get {
...@@ -383,8 +384,7 @@ namespace Google.ProtocolBuffers.Descriptors { ...@@ -383,8 +384,7 @@ namespace Google.ProtocolBuffers.Descriptors {
} else { } else {
// Determine the default default for this field. // Determine the default default for this field.
if (IsRepeated) { if (IsRepeated) {
// FIXME(jonskeet): Find out the correct list type and use that instead. defaultValue = Lists<object>.Empty;
defaultValue = new List<object>();
} else { } else {
switch (MappedType) { switch (MappedType) {
case MappedType.Enum: case MappedType.Enum:
......
...@@ -17,6 +17,8 @@ namespace Google.ProtocolBuffers { ...@@ -17,6 +17,8 @@ namespace Google.ProtocolBuffers {
/// FieldSet class, FieldSet just has a MakeImmutable() method. This is safe so long as /// FieldSet class, FieldSet just has a MakeImmutable() method. This is safe so long as
/// all callers are careful not to let a mutable FieldSet escape into the open. This would /// all callers are careful not to let a mutable FieldSet escape into the open. This would
/// be impossible to guarantee if this were a public class, of course. /// be impossible to guarantee if this were a public class, of course.
///
/// All repeated fields are stored as IList[object] even
/// </summary> /// </summary>
internal class FieldSet { internal class FieldSet {
...@@ -131,7 +133,7 @@ namespace Google.ProtocolBuffers { ...@@ -131,7 +133,7 @@ namespace Google.ProtocolBuffers {
int fieldNumber = WireFormat.GetTagFieldNumber(tag); int fieldNumber = WireFormat.GetTagFieldNumber(tag);
FieldDescriptor field; FieldDescriptor field;
IMessage defaultInstance = null; IMessage defaultFieldInstance = null;
if (type.IsExtensionNumber(fieldNumber)) { if (type.IsExtensionNumber(fieldNumber)) {
ExtensionInfo extension = extensionRegistry[type, fieldNumber]; ExtensionInfo extension = extensionRegistry[type, fieldNumber];
...@@ -139,7 +141,7 @@ namespace Google.ProtocolBuffers { ...@@ -139,7 +141,7 @@ namespace Google.ProtocolBuffers {
field = null; field = null;
} else { } else {
field = extension.Descriptor; field = extension.Descriptor;
defaultInstance = extension.DefaultInstance; defaultFieldInstance = extension.DefaultInstance;
} }
} else { } else {
field = type.FindFieldByNumber(fieldNumber); field = type.FindFieldByNumber(fieldNumber);
...@@ -155,8 +157,8 @@ namespace Google.ProtocolBuffers { ...@@ -155,8 +157,8 @@ namespace Google.ProtocolBuffers {
case FieldType.Group: case FieldType.Group:
case FieldType.Message: { case FieldType.Message: {
IBuilder subBuilder; IBuilder subBuilder;
if (defaultInstance != null) { if (defaultFieldInstance != null) {
subBuilder = defaultInstance.CreateBuilderForType(); subBuilder = defaultFieldInstance.CreateBuilderForType();
} else { } else {
subBuilder = builder.CreateBuilderForField(field); subBuilder = builder.CreateBuilderForField(field);
} }
...@@ -308,7 +310,8 @@ namespace Google.ProtocolBuffers { ...@@ -308,7 +310,8 @@ namespace Google.ProtocolBuffers {
/// <list> /// <list>
/// <item>For singular message values, null is returned.</item> /// <item>For singular message values, null is returned.</item>
/// <item>For singular non-message values, the default value of the field is returned.</item> /// <item>For singular non-message values, the default value of the field is returned.</item>
/// <item>For repeated values, an empty immutable list is returned.</item> /// <item>For repeated values, an empty immutable list is returned. This will be compatible
/// with IList[object], regardless of the type of the repeated item.</item>
/// </list> /// </list>
/// This method returns null if the field is a singular message type /// This method returns null if the field is a singular message type
/// and is not set; in this case it is up to the caller to fetch the /// and is not set; in this case it is up to the caller to fetch the
...@@ -361,7 +364,7 @@ namespace Google.ProtocolBuffers { ...@@ -361,7 +364,7 @@ namespace Google.ProtocolBuffers {
throw new ArgumentException("Indexer specifying field and index can only be called on repeated fields."); throw new ArgumentException("Indexer specifying field and index can only be called on repeated fields.");
} }
return ((List<object>)this[field])[index]; return ((IList<object>) this[field])[index];
} }
set { set {
if (!field.IsRepeated) { if (!field.IsRepeated) {
...@@ -372,15 +375,13 @@ namespace Google.ProtocolBuffers { ...@@ -372,15 +375,13 @@ namespace Google.ProtocolBuffers {
if (!fields.TryGetValue(field, out list)) { if (!fields.TryGetValue(field, out list)) {
throw new ArgumentOutOfRangeException(); throw new ArgumentOutOfRangeException();
} }
((List<object>) list)[index] = value; ((IList<object>) list)[index] = value;
} }
} }
/// <summary> /// <summary>
/// See <see cref="IBuilder.AddRepeatedField" /> /// See <see cref="IBuilder.AddRepeatedField" />
/// </summary> /// </summary>
/// <param name="field"></param>
/// <param name="value"></param>
internal void AddRepeatedField(FieldDescriptor field, object value) { internal void AddRepeatedField(FieldDescriptor field, object value) {
if (!field.IsRepeated) { if (!field.IsRepeated) {
throw new ArgumentException("AddRepeatedField can only be called on repeated fields."); throw new ArgumentException("AddRepeatedField can only be called on repeated fields.");
...@@ -391,7 +392,7 @@ namespace Google.ProtocolBuffers { ...@@ -391,7 +392,7 @@ namespace Google.ProtocolBuffers {
list = new List<object>(); list = new List<object>();
fields[field] = list; fields[field] = list;
} }
((List<object>) list).Add(value); ((IList<object>) list).Add(value);
} }
/// <summary> /// <summary>
...@@ -454,7 +455,7 @@ namespace Google.ProtocolBuffers { ...@@ -454,7 +455,7 @@ namespace Google.ProtocolBuffers {
throw new ArgumentException("GetRepeatedFieldCount() can only be called on repeated fields."); throw new ArgumentException("GetRepeatedFieldCount() can only be called on repeated fields.");
} }
return ((List<object>) this[field]).Count; return ((IList<object>) this[field]).Count;
} }
/// <summary> /// <summary>
...@@ -480,8 +481,8 @@ namespace Google.ProtocolBuffers { ...@@ -480,8 +481,8 @@ namespace Google.ProtocolBuffers {
existingValue = new List<object>(); existingValue = new List<object>();
fields[field] = existingValue; fields[field] = existingValue;
} }
List<object> list = (List<object>)existingValue; IList<object> list = (IList<object>) existingValue;
foreach (object otherValue in (IEnumerable)entry.Value) { foreach (object otherValue in (IEnumerable) entry.Value) {
list.Add(otherValue); list.Add(otherValue);
} }
} else if (field.MappedType == MappedType.Message && existingValue != null) { } else if (field.MappedType == MappedType.Message && existingValue != null) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment