Merge pull request #701 from jskeet/map-views

Implement Keys and Values as views in MapField
diff --git a/csharp/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs b/csharp/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs
index 6e1d804..936e41c 100644
--- a/csharp/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs
+++ b/csharp/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs
@@ -213,6 +213,6 @@
             var descriptor = TestAllTypes.Descriptor;
             Assert.Throws<KeyNotFoundException>(() => descriptor.Fields[999999].ToString());
             Assert.Throws<KeyNotFoundException>(() => descriptor.Fields["not found"].ToString());
-        }
+        }        
     }
 }
diff --git a/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs
index bb8e9bb..901cbf4 100644
--- a/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs
@@ -168,14 +168,16 @@
             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>
         /// Returns <c>true</c> if this field is a packed, repeated field; <c>false</c> otherwise.
         /// </summary>
         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>
diff --git a/csharp/src/Google.Protobuf/Reflection/PartialClasses.cs b/csharp/src/Google.Protobuf/Reflection/PartialClasses.cs
index c7ed434..8c055d6 100644
--- a/csharp/src/Google.Protobuf/Reflection/PartialClasses.cs
+++ b/csharp/src/Google.Protobuf/Reflection/PartialClasses.cs
@@ -44,4 +44,16 @@
             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;

+        }

+    }

 }
\ No newline at end of file
diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.cc b/src/google/protobuf/compiler/csharp/csharp_field_base.cc
index 7e3bbee..cd29bcf 100644
--- a/src/google/protobuf/compiler/csharp/csharp_field_base.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_field_base.cc
@@ -59,7 +59,7 @@
   // repeated fields varies by wire format. The wire format is encoded in the bottom 3 bits, which
   // never effects the tag size.
   int tag_size = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type());
-  uint tag = FixedMakeTag(descriptor_);
+  uint tag = internal::WireFormat::MakeTag(descriptor_);
   uint8 tag_array[5];
   io::CodedOutputStream::WriteTagToArray(tag, tag_array);
   string tag_bytes = SimpleItoa(tag_array[0]);
diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.cc b/src/google/protobuf/compiler/csharp/csharp_helpers.cc
index 46f4fc3..d25dcba 100644
--- a/src/google/protobuf/compiler/csharp/csharp_helpers.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_helpers.cc
@@ -338,17 +338,6 @@
   return StringToBase64(fdp_bytes);
 }
 
-// TODO(jonskeet): Remove this when internal::WireFormat::MakeTag works
-// properly...
-// Workaround for issue #493
-uint FixedMakeTag(const FieldDescriptor* field) {
-  internal::WireFormatLite::WireType field_type = field->is_packed()
-      ? internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED
-      : internal::WireFormat::WireTypeForFieldType(field->type());
-
-  return internal::WireFormatLite::MakeTag(field->number(), field_type);
-}
-
 FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor,
                                          int fieldOrdinal) {
   switch (descriptor->type()) {