| 
					
				 | 
			
			
				@@ -540,17 +540,17 @@ namespace Google.Protobuf 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 case FieldType.Int32: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 case FieldType.SInt32: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 case FieldType.SFixed32: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    return ParseNumericString(keyText, int.Parse, false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    return ParseNumericString(keyText, int.Parse); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 case FieldType.UInt32: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 case FieldType.Fixed32: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    return ParseNumericString(keyText, uint.Parse, false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    return ParseNumericString(keyText, uint.Parse); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 case FieldType.Int64: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 case FieldType.SInt64: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 case FieldType.SFixed64: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    return ParseNumericString(keyText, long.Parse, false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    return ParseNumericString(keyText, long.Parse); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 case FieldType.UInt64: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 case FieldType.Fixed64: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    return ParseNumericString(keyText, ulong.Parse, false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    return ParseNumericString(keyText, ulong.Parse); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 default: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     throw new InvalidProtocolBufferException("Invalid field type for map: " + field.FieldType); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -561,7 +561,6 @@ namespace Google.Protobuf 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             double value = token.NumberValue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             checked 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                // TODO: Validate that it's actually an integer, possibly in terms of the textual representation?                 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 try 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     switch (field.FieldType) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -569,16 +568,20 @@ namespace Google.Protobuf 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         case FieldType.Int32: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         case FieldType.SInt32: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         case FieldType.SFixed32: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            CheckInteger(value); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                             return (int) value; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         case FieldType.UInt32: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         case FieldType.Fixed32: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            CheckInteger(value); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                             return (uint) value; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         case FieldType.Int64: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         case FieldType.SInt64: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         case FieldType.SFixed64: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            CheckInteger(value); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                             return (long) value; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         case FieldType.UInt64: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         case FieldType.Fixed64: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            CheckInteger(value); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                             return (ulong) value; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         case FieldType.Double: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                             return value; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -597,20 +600,32 @@ namespace Google.Protobuf 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                     return float.NegativeInfinity; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                throw new InvalidProtocolBufferException("Value out of range: " + value); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                throw new InvalidProtocolBufferException($"Value out of range: {value}"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                             return (float) value; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         default: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            throw new InvalidProtocolBufferException("Unsupported conversion from JSON number for field type " + field.FieldType); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            throw new InvalidProtocolBufferException($"Unsupported conversion from JSON number for field type {field.FieldType}"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 catch (OverflowException) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    throw new InvalidProtocolBufferException("Value out of range: " + value); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    throw new InvalidProtocolBufferException($"Value out of range: {value}"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        private static void CheckInteger(double value) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (double.IsInfinity(value) || double.IsNaN(value)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                throw new InvalidProtocolBufferException($"Value not an integer: {value}"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (value != Math.Floor(value)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                throw new InvalidProtocolBufferException($"Value not an integer: {value}"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            }             
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         private static object ParseSingleStringValue(FieldDescriptor field, string text) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             switch (field.FieldType) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -622,43 +637,35 @@ namespace Google.Protobuf 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 case FieldType.Int32: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 case FieldType.SInt32: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 case FieldType.SFixed32: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    return ParseNumericString(text, int.Parse, false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    return ParseNumericString(text, int.Parse); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 case FieldType.UInt32: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 case FieldType.Fixed32: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    return ParseNumericString(text, uint.Parse, false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    return ParseNumericString(text, uint.Parse); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 case FieldType.Int64: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 case FieldType.SInt64: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 case FieldType.SFixed64: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    return ParseNumericString(text, long.Parse, false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    return ParseNumericString(text, long.Parse); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 case FieldType.UInt64: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 case FieldType.Fixed64: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    return ParseNumericString(text, ulong.Parse, false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    return ParseNumericString(text, ulong.Parse); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 case FieldType.Double: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    double d = ParseNumericString(text, double.Parse, true); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    // double.Parse can return +/- infinity on Mono for non-infinite values which are out of range for double. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    if (double.IsInfinity(d) && !text.Contains("Infinity")) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        throw new InvalidProtocolBufferException("Invalid numeric value: " + text); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    double d = ParseNumericString(text, double.Parse); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    ValidateInfinityAndNan(text, double.IsPositiveInfinity(d), double.IsNegativeInfinity(d), double.IsNaN(d)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     return d; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 case FieldType.Float: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    float f = ParseNumericString(text, float.Parse, true); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    // float.Parse can return +/- infinity on Mono for non-infinite values which are out of range for float. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    if (float.IsInfinity(f) && !text.Contains("Infinity")) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        throw new InvalidProtocolBufferException("Invalid numeric value: " + text); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    float f = ParseNumericString(text, float.Parse); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    ValidateInfinityAndNan(text, float.IsPositiveInfinity(f), float.IsNegativeInfinity(f), float.IsNaN(f)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     return f; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 case FieldType.Enum: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     var enumValue = field.EnumType.FindValueByName(text); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     if (enumValue == null) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        throw new InvalidProtocolBufferException("Invalid enum value: " + text + " for enum type: " + field.EnumType.FullName); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        throw new InvalidProtocolBufferException($"Invalid enum value: {text} for enum type: {field.EnumType.FullName}"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     // Just return it as an int, and let the CLR convert it. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     return enumValue.Number; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 default: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    throw new InvalidProtocolBufferException("Unsupported conversion from JSON string for field type " + field.FieldType); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    throw new InvalidProtocolBufferException($"Unsupported conversion from JSON string for field type {field.FieldType}"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -670,43 +677,53 @@ namespace Google.Protobuf 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             return field.MessageType.Parser.CreateTemplate(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        private static T ParseNumericString<T>(string text, Func<string, NumberStyles, IFormatProvider, T> parser, bool floatingPoint) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        private static T ParseNumericString<T>(string text, Func<string, NumberStyles, IFormatProvider, T> parser) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            // TODO: Prohibit leading zeroes (but allow 0!) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            // TODO: Validate handling of "Infinity" etc. (Should be case sensitive, no leading whitespace etc) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             // Can't prohibit this with NumberStyles. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if (text.StartsWith("+")) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                throw new InvalidProtocolBufferException("Invalid numeric value: " + text); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                throw new InvalidProtocolBufferException($"Invalid numeric value: {text}"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if (text.StartsWith("0") && text.Length > 1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 if (text[1] >= '0' && text[1] <= '9') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    throw new InvalidProtocolBufferException("Invalid numeric value: " + text); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    throw new InvalidProtocolBufferException($"Invalid numeric value: {text}"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             else if (text.StartsWith("-0") && text.Length > 2) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 if (text[2] >= '0' && text[2] <= '9') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    throw new InvalidProtocolBufferException("Invalid numeric value: " + text); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    throw new InvalidProtocolBufferException($"Invalid numeric value: {text}"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             try 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                var styles = floatingPoint 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    ? NumberStyles.AllowLeadingSign | NumberStyles.AllowDecimalPoint | NumberStyles.AllowExponent 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    : NumberStyles.AllowLeadingSign; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                return parser(text, styles, CultureInfo.InvariantCulture); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                return parser(text, NumberStyles.AllowLeadingSign | NumberStyles.AllowDecimalPoint | NumberStyles.AllowExponent, CultureInfo.InvariantCulture); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             catch (FormatException) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                throw new InvalidProtocolBufferException("Invalid numeric value for type: " + text); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                throw new InvalidProtocolBufferException($"Invalid numeric value for type: {text}"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             catch (OverflowException) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                throw new InvalidProtocolBufferException("Value out of range: " + text); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                throw new InvalidProtocolBufferException($"Value out of range: {text}"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        /// <summary> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        /// Checks that any infinite/NaN values originated from the correct text. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        /// This corrects the lenient whitespace handling of double.Parse/float.Parse, as well as the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        /// way that Mono parses out-of-range values as infinity. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        /// </summary> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        private static void ValidateInfinityAndNan(string text, bool isPositiveInfinity, bool isNegativeInfinity, bool isNaN) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if ((isPositiveInfinity && text != "Infinity") || 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                (isNegativeInfinity && text != "-Infinity") || 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                (isNaN && text != "NaN")) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                throw new InvalidProtocolBufferException($"Invalid numeric value: {text}"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -719,7 +736,7 @@ namespace Google.Protobuf 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             var match = TimestampRegex.Match(token.StringValue); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if (!match.Success) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                throw new InvalidProtocolBufferException("Invalid Timestamp value: " + token.StringValue); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                throw new InvalidProtocolBufferException($"Invalid Timestamp value: {token.StringValue}"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             var dateTime = match.Groups["datetime"].Value; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             var subseconds = match.Groups["subseconds"].Value; 
			 |