Browse Source

Merge pull request #699 from jskeet/validate_packed

 Make FieldDescriptor.IsPacked work appropriately.
Jon Skeet 10 years ago
parent
commit
c2c42053bc

+ 1 - 1
csharp/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs

@@ -213,6 +213,6 @@ namespace Google.Protobuf.Reflection
             var descriptor = TestAllTypes.Descriptor;
             var descriptor = TestAllTypes.Descriptor;
             Assert.Throws<KeyNotFoundException>(() => descriptor.Fields[999999].ToString());
             Assert.Throws<KeyNotFoundException>(() => descriptor.Fields[999999].ToString());
             Assert.Throws<KeyNotFoundException>(() => descriptor.Fields["not found"].ToString());
             Assert.Throws<KeyNotFoundException>(() => descriptor.Fields["not found"].ToString());
-        }
+        }        
     }
     }
 }
 }

+ 5 - 3
csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs

@@ -168,14 +168,16 @@ namespace Google.Protobuf.Reflection
             get { return fieldType == FieldType.Message && messageType.Proto.Options != null && messageType.Proto.Options.MapEntry; }
             get { return fieldType == FieldType.Message && messageType.Proto.Options != null && messageType.Proto.Options.MapEntry; }
         }
         }
 
 
-        // TODO(jonskeet): Check whether this is correct with proto3, where we default to packed...
-
         /// <summary>
         /// <summary>
         /// Returns <c>true</c> if this field is a packed, repeated field; <c>false</c> otherwise.
         /// Returns <c>true</c> if this field is a packed, repeated field; <c>false</c> otherwise.
         /// </summary>
         /// </summary>
         public bool IsPacked
         public bool IsPacked
         {
         {
-            get { return Proto.Options != null && Proto.Options.Packed; }
+            // Note the || rather than && here - we're effectively defaulting to packed, because that *is*
+            // the default in proto3, which is all we support. We may give the wrong result for the protos
+            // within descriptor.proto, but that's okay, as they're never exposed and we don't use IsPacked
+            // within the runtime.
+            get { return Proto.Options == null || Proto.Options.Packed; }
         }        
         }        
 
 
         /// <summary>
         /// <summary>

+ 12 - 0
csharp/src/Google.Protobuf/Reflection/PartialClasses.cs

@@ -44,4 +44,16 @@ namespace Google.Protobuf.Reflection
             OneofIndex = -1;
             OneofIndex = -1;
         }
         }
     }
     }
+
+    internal partial class FieldOptions
+    {
+        // We can't tell the difference between "explicitly set to false" and "not set"
+        // in proto3, but we need to tell the difference for FieldDescriptor.IsPacked.
+        // This won't work if we ever need to support proto2, but at that point we'll be
+        // able to remove this hack and use field presence instead. 
+        partial void OnConstruction()
+        {
+            Packed = true;
+        }
+    }
 }
 }