Commit 24638088 authored by Hao Nguyen's avatar Hao Nguyen

Make Protobuf compatible with C# 6

parent 1484b580
...@@ -120,7 +120,8 @@ namespace Google.Protobuf ...@@ -120,7 +120,8 @@ namespace Google.Protobuf
return this; return this;
} }
if (!node.Children.TryGetValue(part, out var childNode)) Node childNode;
if (!node.Children.TryGetValue(part, out childNode))
{ {
createNewBranch = true; createNewBranch = true;
childNode = new Node(); childNode = new Node();
...@@ -361,4 +362,4 @@ namespace Google.Protobuf ...@@ -361,4 +362,4 @@ namespace Google.Protobuf
} }
} }
} }
} }
\ No newline at end of file
...@@ -98,64 +98,65 @@ namespace Google.Protobuf.Reflection ...@@ -98,64 +98,65 @@ namespace Google.Protobuf.Reflection
} }
} }
return dictionary; return dictionary;
}
IDescriptor FindDescriptorForPath(IList<int> path) private IDescriptor FindDescriptorForPath(IList<int> path)
{
// All complete declarations have an even, non-empty path length
// (There can be an empty path for a descriptor declaration, but that can't have any comments,
// so we currently ignore it.)
if (path.Count == 0 || (path.Count & 1) != 0)
{ {
// All complete declarations have an even, non-empty path length return null;
// (There can be an empty path for a descriptor declaration, but that can't have any comments, }
// so we currently ignore it.) IReadOnlyList<DescriptorBase> topLevelList = GetNestedDescriptorListForField(path[0]);
if (path.Count == 0 || (path.Count & 1) != 0) DescriptorBase current = GetDescriptorFromList(topLevelList, path[1]);
{
return null;
}
IReadOnlyList<DescriptorBase> topLevelList = GetNestedDescriptorListForField(path[0]);
DescriptorBase current = GetDescriptorFromList(topLevelList, path[1]);
for (int i = 2; current != null && i < path.Count; i += 2) for (int i = 2; current != null && i < path.Count; i += 2)
{ {
var list = current.GetNestedDescriptorListForField(path[i]); var list = current.GetNestedDescriptorListForField(path[i]);
current = GetDescriptorFromList(list, path[i + 1]); current = GetDescriptorFromList(list, path[i + 1]);
}
return current;
} }
return current;
}
DescriptorBase GetDescriptorFromList(IReadOnlyList<DescriptorBase> list, int index) private DescriptorBase GetDescriptorFromList(IReadOnlyList<DescriptorBase> list, int index)
{
// This is fine: it may be a newer version of protobuf than we understand, with a new descriptor
// field.
if (list == null)
{ {
// This is fine: it may be a newer version of protobuf than we understand, with a new descriptor return null;
// field. }
if (list == null) // We *could* return null to silently continue, but this is basically data corruption.
{ if (index < 0 || index >= list.Count)
return null; {
} // We don't have much extra information to give at this point unfortunately. If this becomes a problem,
// We *could* return null to silently continue, but this is basically data corruption. // we can pass in the complete path and report that and the file name.
if (index < 0 || index >= list.Count) throw new InvalidProtocolBufferException($"Invalid descriptor location path: index out of range");
{
// We don't have much extra information to give at this point unfortunately. If this becomes a problem,
// we can pass in the complete path and report that and the file name.
throw new InvalidProtocolBufferException($"Invalid descriptor location path: index out of range");
}
return list[index];
} }
return list[index];
}
IReadOnlyList<DescriptorBase> GetNestedDescriptorListForField(int fieldNumber) private IReadOnlyList<DescriptorBase> GetNestedDescriptorListForField(int fieldNumber)
{
switch (fieldNumber)
{ {
switch (fieldNumber) case FileDescriptorProto.ServiceFieldNumber:
{ return (IReadOnlyList<DescriptorBase>) Services;
case FileDescriptorProto.ServiceFieldNumber: case FileDescriptorProto.MessageTypeFieldNumber:
return (IReadOnlyList<DescriptorBase>) Services; return (IReadOnlyList<DescriptorBase>) MessageTypes;
case FileDescriptorProto.MessageTypeFieldNumber: case FileDescriptorProto.EnumTypeFieldNumber:
return (IReadOnlyList<DescriptorBase>) MessageTypes; return (IReadOnlyList<DescriptorBase>) EnumTypes;
case FileDescriptorProto.EnumTypeFieldNumber: default:
return (IReadOnlyList<DescriptorBase>) EnumTypes; return null;
default:
return null;
}
} }
} }
internal DescriptorDeclaration GetDeclaration(IDescriptor descriptor) internal DescriptorDeclaration GetDeclaration(IDescriptor descriptor)
{ {
declarations.Value.TryGetValue(descriptor, out var declaration); DescriptorDeclaration declaration;
declarations.Value.TryGetValue(descriptor, out declaration);
return declaration; return declaration;
} }
...@@ -191,7 +192,8 @@ namespace Google.Protobuf.Reflection ...@@ -191,7 +192,8 @@ namespace Google.Protobuf.Reflection
throw new DescriptorValidationException(@this, "Invalid public dependency index."); throw new DescriptorValidationException(@this, "Invalid public dependency index.");
} }
string name = proto.Dependency[index]; string name = proto.Dependency[index];
if (!nameToFileMap.TryGetValue(name, out var file)) FileDescriptor file;
if (!nameToFileMap.TryGetValue(name, out file))
{ {
if (!allowUnknownDependencies) if (!allowUnknownDependencies)
{ {
...@@ -414,7 +416,8 @@ namespace Google.Protobuf.Reflection ...@@ -414,7 +416,8 @@ namespace Google.Protobuf.Reflection
var dependencies = new List<FileDescriptor>(); var dependencies = new List<FileDescriptor>();
foreach (var dependencyName in proto.Dependency) foreach (var dependencyName in proto.Dependency)
{ {
if (!descriptorsByName.TryGetValue(dependencyName, out var dependency)) FileDescriptor dependency;
if (!descriptorsByName.TryGetValue(dependencyName, out dependency))
{ {
throw new ArgumentException($"Dependency missing: {dependencyName}"); throw new ArgumentException($"Dependency missing: {dependencyName}");
} }
......
...@@ -60,13 +60,22 @@ namespace Google.Protobuf.Reflection ...@@ -60,13 +60,22 @@ namespace Google.Protobuf.Reflection
if (descriptor.File.Proto.Syntax == "proto2") if (descriptor.File.Proto.Syntax == "proto2")
{ {
MethodInfo hasMethod = property.DeclaringType.GetRuntimeProperty("Has" + property.Name).GetMethod; MethodInfo hasMethod = property.DeclaringType.GetRuntimeProperty("Has" + property.Name).GetMethod;
hasDelegate = ReflectionUtil.CreateFuncIMessageBool(hasMethod ?? throw new ArgumentException("Not all required properties/methods are available")); if (hasMethod == null) {
throw new ArgumentException("Not all required properties/methods are available");
}
hasDelegate = ReflectionUtil.CreateFuncIMessageBool(hasMethod);
MethodInfo clearMethod = property.DeclaringType.GetRuntimeMethod("Clear" + property.Name, ReflectionUtil.EmptyTypes); MethodInfo clearMethod = property.DeclaringType.GetRuntimeMethod("Clear" + property.Name, ReflectionUtil.EmptyTypes);
clearDelegate = ReflectionUtil.CreateActionIMessage(clearMethod ?? throw new ArgumentException("Not all required properties/methods are available")); if (clearMethod == null) {
throw new ArgumentException("Not all required properties/methods are available");
}
clearDelegate = ReflectionUtil.CreateActionIMessage(clearMethod);
} }
else else
{ {
hasDelegate = (_) => throw new InvalidOperationException("HasValue is not implemented for proto3 fields"); var clrType = property.PropertyType; hasDelegate = message => {
throw new InvalidOperationException("HasValue is not implemented for proto3 fields");
};
var clrType = property.PropertyType;
// TODO: Validate that this is a reasonable single field? (Should be a value type, a message type, or string/ByteString.) // TODO: Validate that this is a reasonable single field? (Should be a value type, a message type, or string/ByteString.)
object defaultValue = object defaultValue =
......
...@@ -308,7 +308,7 @@ namespace Google.Protobuf.WellKnownTypes ...@@ -308,7 +308,7 @@ namespace Google.Protobuf.WellKnownTypes
/// <returns>true if the two timestamps refer to the same nanosecond</returns> /// <returns>true if the two timestamps refer to the same nanosecond</returns>
public static bool operator ==(Timestamp a, Timestamp b) public static bool operator ==(Timestamp a, Timestamp b)
{ {
return ReferenceEquals(a, b) || (a is null ? (b is null ? true : false) : a.Equals(b)); return ReferenceEquals(a, b) || (a == null ? (b == null ? true : false) : a.Equals(b));
} }
/// <summary> /// <summary>
......
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