Merge pull request #593 from jskeet/reflection-namespace
Change the reflection namespace in C#pull/599/head
commit
f30c3d35c6
49 changed files with 3331 additions and 3355 deletions
@ -1,225 +1,223 @@ |
||||
#region Copyright notice and license |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2008 Google Inc. All rights reserved. |
||||
// https://developers.google.com/protocol-buffers/ |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
#endregion |
||||
|
||||
using System.Linq; |
||||
using Google.Protobuf.DescriptorProtos; |
||||
using Google.Protobuf.Descriptors; |
||||
using Google.Protobuf.TestProtos; |
||||
using NUnit.Framework; |
||||
|
||||
namespace Google.Protobuf |
||||
{ |
||||
/// <summary> |
||||
/// Tests for descriptors. (Not in its own namespace or broken up into individual classes as the |
||||
/// size doesn't warrant it. On the other hand, this makes me feel a bit dirty...) |
||||
/// </summary> |
||||
public class DescriptorsTest |
||||
{ |
||||
[Test] |
||||
public void FileDescriptor() |
||||
{ |
||||
FileDescriptor file = UnittestProto3.Descriptor; |
||||
|
||||
Assert.AreEqual("google/protobuf/unittest_proto3.proto", file.Name); |
||||
Assert.AreEqual("protobuf_unittest", file.Package); |
||||
|
||||
Assert.AreEqual("UnittestProto", file.Proto.Options.JavaOuterClassname); |
||||
Assert.AreEqual("google/protobuf/unittest_proto3.proto", file.Proto.Name); |
||||
|
||||
// unittest.proto doesn't have any public imports, but unittest_import.proto does. |
||||
Assert.AreEqual(0, file.PublicDependencies.Count); |
||||
Assert.AreEqual(1, UnittestImportProto3.Descriptor.PublicDependencies.Count); |
||||
Assert.AreEqual(UnittestImportPublicProto3.Descriptor, UnittestImportProto3.Descriptor.PublicDependencies[0]); |
||||
|
||||
Assert.AreEqual(1, file.Dependencies.Count); |
||||
Assert.AreEqual(UnittestImportProto3.Descriptor, file.Dependencies[0]); |
||||
|
||||
MessageDescriptor messageType = TestAllTypes.Descriptor; |
||||
Assert.AreEqual(messageType, file.MessageTypes[0]); |
||||
Assert.AreEqual(messageType, file.FindTypeByName<MessageDescriptor>("TestAllTypes")); |
||||
Assert.Null(file.FindTypeByName<MessageDescriptor>("NoSuchType")); |
||||
Assert.Null(file.FindTypeByName<MessageDescriptor>("protobuf_unittest.TestAllTypes")); |
||||
for (int i = 0; i < file.MessageTypes.Count; i++) |
||||
{ |
||||
Assert.AreEqual(i, file.MessageTypes[i].Index); |
||||
} |
||||
|
||||
Assert.AreEqual(file.EnumTypes[0], file.FindTypeByName<EnumDescriptor>("ForeignEnum")); |
||||
Assert.Null(file.FindTypeByName<EnumDescriptor>("NoSuchType")); |
||||
Assert.Null(file.FindTypeByName<EnumDescriptor>("protobuf_unittest.ForeignEnum")); |
||||
Assert.AreEqual(1, UnittestImportProto3.Descriptor.EnumTypes.Count); |
||||
Assert.AreEqual("ImportEnum", UnittestImportProto3.Descriptor.EnumTypes[0].Name); |
||||
for (int i = 0; i < file.EnumTypes.Count; i++) |
||||
{ |
||||
Assert.AreEqual(i, file.EnumTypes[i].Index); |
||||
} |
||||
} |
||||
|
||||
[Test] |
||||
public void MessageDescriptor() |
||||
{ |
||||
MessageDescriptor messageType = TestAllTypes.Descriptor; |
||||
MessageDescriptor nestedType = TestAllTypes.Types.NestedMessage.Descriptor; |
||||
|
||||
Assert.AreEqual("TestAllTypes", messageType.Name); |
||||
Assert.AreEqual("protobuf_unittest.TestAllTypes", messageType.FullName); |
||||
Assert.AreEqual(UnittestProto3.Descriptor, messageType.File); |
||||
Assert.IsNull(messageType.ContainingType); |
||||
Assert.IsNull(messageType.Proto.Options); |
||||
|
||||
Assert.AreEqual("TestAllTypes", messageType.Name); |
||||
|
||||
Assert.AreEqual("NestedMessage", nestedType.Name); |
||||
Assert.AreEqual("protobuf_unittest.TestAllTypes.NestedMessage", nestedType.FullName); |
||||
Assert.AreEqual(UnittestProto3.Descriptor, nestedType.File); |
||||
Assert.AreEqual(messageType, nestedType.ContainingType); |
||||
|
||||
FieldDescriptor field = messageType.Fields[0]; |
||||
Assert.AreEqual("single_int32", field.Name); |
||||
Assert.AreEqual(field, messageType.FindDescriptor<FieldDescriptor>("single_int32")); |
||||
Assert.Null(messageType.FindDescriptor<FieldDescriptor>("no_such_field")); |
||||
Assert.AreEqual(field, messageType.FindFieldByNumber(1)); |
||||
Assert.Null(messageType.FindFieldByNumber(571283)); |
||||
for (int i = 0; i < messageType.Fields.Count; i++) |
||||
{ |
||||
Assert.AreEqual(i, messageType.Fields[i].Index); |
||||
} |
||||
|
||||
Assert.AreEqual(nestedType, messageType.NestedTypes[0]); |
||||
Assert.AreEqual(nestedType, messageType.FindDescriptor<MessageDescriptor>("NestedMessage")); |
||||
Assert.Null(messageType.FindDescriptor<MessageDescriptor>("NoSuchType")); |
||||
for (int i = 0; i < messageType.NestedTypes.Count; i++) |
||||
{ |
||||
Assert.AreEqual(i, messageType.NestedTypes[i].Index); |
||||
} |
||||
|
||||
Assert.AreEqual(messageType.EnumTypes[0], messageType.FindDescriptor<EnumDescriptor>("NestedEnum")); |
||||
Assert.Null(messageType.FindDescriptor<EnumDescriptor>("NoSuchType")); |
||||
for (int i = 0; i < messageType.EnumTypes.Count; i++) |
||||
{ |
||||
Assert.AreEqual(i, messageType.EnumTypes[i].Index); |
||||
} |
||||
} |
||||
|
||||
[Test] |
||||
public void FieldDescriptor() |
||||
{ |
||||
MessageDescriptor messageType = TestAllTypes.Descriptor; |
||||
FieldDescriptor primitiveField = messageType.FindDescriptor<FieldDescriptor>("single_int32"); |
||||
FieldDescriptor enumField = messageType.FindDescriptor<FieldDescriptor>("single_nested_enum"); |
||||
FieldDescriptor messageField = messageType.FindDescriptor<FieldDescriptor>("single_foreign_message"); |
||||
|
||||
Assert.AreEqual("single_int32", primitiveField.Name); |
||||
Assert.AreEqual("protobuf_unittest.TestAllTypes.single_int32", |
||||
primitiveField.FullName); |
||||
Assert.AreEqual(1, primitiveField.FieldNumber); |
||||
Assert.AreEqual(messageType, primitiveField.ContainingType); |
||||
Assert.AreEqual(UnittestProto3.Descriptor, primitiveField.File); |
||||
Assert.AreEqual(FieldType.Int32, primitiveField.FieldType); |
||||
Assert.IsNull(primitiveField.Proto.Options); |
||||
|
||||
Assert.AreEqual("single_nested_enum", enumField.Name); |
||||
Assert.AreEqual(FieldType.Enum, enumField.FieldType); |
||||
// Assert.AreEqual(TestAllTypes.Types.NestedEnum.DescriptorProtoFile, enumField.EnumType); |
||||
|
||||
Assert.AreEqual("single_foreign_message", messageField.Name); |
||||
Assert.AreEqual(FieldType.Message, messageField.FieldType); |
||||
Assert.AreEqual(ForeignMessage.Descriptor, messageField.MessageType); |
||||
} |
||||
|
||||
[Test] |
||||
public void FieldDescriptorLabel() |
||||
{ |
||||
FieldDescriptor singleField = |
||||
TestAllTypes.Descriptor.FindDescriptor<FieldDescriptor>("single_int32"); |
||||
FieldDescriptor repeatedField = |
||||
TestAllTypes.Descriptor.FindDescriptor<FieldDescriptor>("repeated_int32"); |
||||
|
||||
Assert.IsFalse(singleField.IsRepeated); |
||||
Assert.IsTrue(repeatedField.IsRepeated); |
||||
} |
||||
|
||||
[Test] |
||||
public void EnumDescriptor() |
||||
{ |
||||
// Note: this test is a bit different to the Java version because there's no static way of getting to the descriptor |
||||
EnumDescriptor enumType = UnittestProto3.Descriptor.FindTypeByName<EnumDescriptor>("ForeignEnum"); |
||||
EnumDescriptor nestedType = TestAllTypes.Descriptor.FindDescriptor<EnumDescriptor>("NestedEnum"); |
||||
|
||||
Assert.AreEqual("ForeignEnum", enumType.Name); |
||||
Assert.AreEqual("protobuf_unittest.ForeignEnum", enumType.FullName); |
||||
Assert.AreEqual(UnittestProto3.Descriptor, enumType.File); |
||||
Assert.Null(enumType.ContainingType); |
||||
Assert.Null(enumType.Proto.Options); |
||||
|
||||
Assert.AreEqual("NestedEnum", nestedType.Name); |
||||
Assert.AreEqual("protobuf_unittest.TestAllTypes.NestedEnum", |
||||
nestedType.FullName); |
||||
Assert.AreEqual(UnittestProto3.Descriptor, nestedType.File); |
||||
Assert.AreEqual(TestAllTypes.Descriptor, nestedType.ContainingType); |
||||
|
||||
EnumValueDescriptor value = enumType.FindValueByName("FOREIGN_FOO"); |
||||
Assert.AreEqual(value, enumType.Values[1]); |
||||
Assert.AreEqual("FOREIGN_FOO", value.Name); |
||||
Assert.AreEqual(4, value.Number); |
||||
Assert.AreEqual((int) ForeignEnum.FOREIGN_FOO, value.Number); |
||||
Assert.AreEqual(value, enumType.FindValueByNumber(4)); |
||||
Assert.Null(enumType.FindValueByName("NO_SUCH_VALUE")); |
||||
for (int i = 0; i < enumType.Values.Count; i++) |
||||
{ |
||||
Assert.AreEqual(i, enumType.Values[i].Index); |
||||
} |
||||
} |
||||
|
||||
[Test] |
||||
public void OneofDescriptor() |
||||
{ |
||||
OneofDescriptor descriptor = TestAllTypes.Descriptor.FindDescriptor<OneofDescriptor>("oneof_field"); |
||||
Assert.AreEqual("oneof_field", descriptor.Name); |
||||
Assert.AreEqual("protobuf_unittest.TestAllTypes.oneof_field", descriptor.FullName); |
||||
|
||||
var expectedFields = new[] { |
||||
TestAllTypes.OneofBytesFieldNumber, |
||||
TestAllTypes.OneofNestedMessageFieldNumber, |
||||
TestAllTypes.OneofStringFieldNumber, |
||||
TestAllTypes.OneofUint32FieldNumber } |
||||
.Select(fieldNumber => TestAllTypes.Descriptor.FindFieldByNumber(fieldNumber)) |
||||
.ToList(); |
||||
foreach (var field in expectedFields) |
||||
{ |
||||
Assert.AreSame(descriptor, field.ContainingOneof); |
||||
} |
||||
|
||||
CollectionAssert.AreEquivalent(expectedFields, descriptor.Fields); |
||||
} |
||||
} |
||||
#region Copyright notice and license |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2008 Google Inc. All rights reserved. |
||||
// https://developers.google.com/protocol-buffers/ |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
#endregion |
||||
|
||||
using System.Linq; |
||||
using Google.Protobuf.TestProtos; |
||||
using NUnit.Framework; |
||||
|
||||
namespace Google.Protobuf.Reflection |
||||
{ |
||||
/// <summary> |
||||
/// Tests for descriptors. (Not in its own namespace or broken up into individual classes as the |
||||
/// size doesn't warrant it. On the other hand, this makes me feel a bit dirty...) |
||||
/// </summary> |
||||
public class DescriptorsTest |
||||
{ |
||||
[Test] |
||||
public void FileDescriptor() |
||||
{ |
||||
FileDescriptor file = UnittestProto3.Descriptor; |
||||
|
||||
Assert.AreEqual("google/protobuf/unittest_proto3.proto", file.Name); |
||||
Assert.AreEqual("protobuf_unittest", file.Package); |
||||
|
||||
Assert.AreEqual("UnittestProto", file.Proto.Options.JavaOuterClassname); |
||||
Assert.AreEqual("google/protobuf/unittest_proto3.proto", file.Proto.Name); |
||||
|
||||
// unittest.proto doesn't have any public imports, but unittest_import.proto does. |
||||
Assert.AreEqual(0, file.PublicDependencies.Count); |
||||
Assert.AreEqual(1, UnittestImportProto3.Descriptor.PublicDependencies.Count); |
||||
Assert.AreEqual(UnittestImportPublicProto3.Descriptor, UnittestImportProto3.Descriptor.PublicDependencies[0]); |
||||
|
||||
Assert.AreEqual(1, file.Dependencies.Count); |
||||
Assert.AreEqual(UnittestImportProto3.Descriptor, file.Dependencies[0]); |
||||
|
||||
MessageDescriptor messageType = TestAllTypes.Descriptor; |
||||
Assert.AreEqual(messageType, file.MessageTypes[0]); |
||||
Assert.AreEqual(messageType, file.FindTypeByName<MessageDescriptor>("TestAllTypes")); |
||||
Assert.Null(file.FindTypeByName<MessageDescriptor>("NoSuchType")); |
||||
Assert.Null(file.FindTypeByName<MessageDescriptor>("protobuf_unittest.TestAllTypes")); |
||||
for (int i = 0; i < file.MessageTypes.Count; i++) |
||||
{ |
||||
Assert.AreEqual(i, file.MessageTypes[i].Index); |
||||
} |
||||
|
||||
Assert.AreEqual(file.EnumTypes[0], file.FindTypeByName<EnumDescriptor>("ForeignEnum")); |
||||
Assert.Null(file.FindTypeByName<EnumDescriptor>("NoSuchType")); |
||||
Assert.Null(file.FindTypeByName<EnumDescriptor>("protobuf_unittest.ForeignEnum")); |
||||
Assert.AreEqual(1, UnittestImportProto3.Descriptor.EnumTypes.Count); |
||||
Assert.AreEqual("ImportEnum", UnittestImportProto3.Descriptor.EnumTypes[0].Name); |
||||
for (int i = 0; i < file.EnumTypes.Count; i++) |
||||
{ |
||||
Assert.AreEqual(i, file.EnumTypes[i].Index); |
||||
} |
||||
} |
||||
|
||||
[Test] |
||||
public void MessageDescriptor() |
||||
{ |
||||
MessageDescriptor messageType = TestAllTypes.Descriptor; |
||||
MessageDescriptor nestedType = TestAllTypes.Types.NestedMessage.Descriptor; |
||||
|
||||
Assert.AreEqual("TestAllTypes", messageType.Name); |
||||
Assert.AreEqual("protobuf_unittest.TestAllTypes", messageType.FullName); |
||||
Assert.AreEqual(UnittestProto3.Descriptor, messageType.File); |
||||
Assert.IsNull(messageType.ContainingType); |
||||
Assert.IsNull(messageType.Proto.Options); |
||||
|
||||
Assert.AreEqual("TestAllTypes", messageType.Name); |
||||
|
||||
Assert.AreEqual("NestedMessage", nestedType.Name); |
||||
Assert.AreEqual("protobuf_unittest.TestAllTypes.NestedMessage", nestedType.FullName); |
||||
Assert.AreEqual(UnittestProto3.Descriptor, nestedType.File); |
||||
Assert.AreEqual(messageType, nestedType.ContainingType); |
||||
|
||||
FieldDescriptor field = messageType.Fields[0]; |
||||
Assert.AreEqual("single_int32", field.Name); |
||||
Assert.AreEqual(field, messageType.FindDescriptor<FieldDescriptor>("single_int32")); |
||||
Assert.Null(messageType.FindDescriptor<FieldDescriptor>("no_such_field")); |
||||
Assert.AreEqual(field, messageType.FindFieldByNumber(1)); |
||||
Assert.Null(messageType.FindFieldByNumber(571283)); |
||||
for (int i = 0; i < messageType.Fields.Count; i++) |
||||
{ |
||||
Assert.AreEqual(i, messageType.Fields[i].Index); |
||||
} |
||||
|
||||
Assert.AreEqual(nestedType, messageType.NestedTypes[0]); |
||||
Assert.AreEqual(nestedType, messageType.FindDescriptor<MessageDescriptor>("NestedMessage")); |
||||
Assert.Null(messageType.FindDescriptor<MessageDescriptor>("NoSuchType")); |
||||
for (int i = 0; i < messageType.NestedTypes.Count; i++) |
||||
{ |
||||
Assert.AreEqual(i, messageType.NestedTypes[i].Index); |
||||
} |
||||
|
||||
Assert.AreEqual(messageType.EnumTypes[0], messageType.FindDescriptor<EnumDescriptor>("NestedEnum")); |
||||
Assert.Null(messageType.FindDescriptor<EnumDescriptor>("NoSuchType")); |
||||
for (int i = 0; i < messageType.EnumTypes.Count; i++) |
||||
{ |
||||
Assert.AreEqual(i, messageType.EnumTypes[i].Index); |
||||
} |
||||
} |
||||
|
||||
[Test] |
||||
public void FieldDescriptor() |
||||
{ |
||||
MessageDescriptor messageType = TestAllTypes.Descriptor; |
||||
FieldDescriptor primitiveField = messageType.FindDescriptor<FieldDescriptor>("single_int32"); |
||||
FieldDescriptor enumField = messageType.FindDescriptor<FieldDescriptor>("single_nested_enum"); |
||||
FieldDescriptor messageField = messageType.FindDescriptor<FieldDescriptor>("single_foreign_message"); |
||||
|
||||
Assert.AreEqual("single_int32", primitiveField.Name); |
||||
Assert.AreEqual("protobuf_unittest.TestAllTypes.single_int32", |
||||
primitiveField.FullName); |
||||
Assert.AreEqual(1, primitiveField.FieldNumber); |
||||
Assert.AreEqual(messageType, primitiveField.ContainingType); |
||||
Assert.AreEqual(UnittestProto3.Descriptor, primitiveField.File); |
||||
Assert.AreEqual(FieldType.Int32, primitiveField.FieldType); |
||||
Assert.IsNull(primitiveField.Proto.Options); |
||||
|
||||
Assert.AreEqual("single_nested_enum", enumField.Name); |
||||
Assert.AreEqual(FieldType.Enum, enumField.FieldType); |
||||
// Assert.AreEqual(TestAllTypes.Types.NestedEnum.DescriptorProtoFile, enumField.EnumType); |
||||
|
||||
Assert.AreEqual("single_foreign_message", messageField.Name); |
||||
Assert.AreEqual(FieldType.Message, messageField.FieldType); |
||||
Assert.AreEqual(ForeignMessage.Descriptor, messageField.MessageType); |
||||
} |
||||
|
||||
[Test] |
||||
public void FieldDescriptorLabel() |
||||
{ |
||||
FieldDescriptor singleField = |
||||
TestAllTypes.Descriptor.FindDescriptor<FieldDescriptor>("single_int32"); |
||||
FieldDescriptor repeatedField = |
||||
TestAllTypes.Descriptor.FindDescriptor<FieldDescriptor>("repeated_int32"); |
||||
|
||||
Assert.IsFalse(singleField.IsRepeated); |
||||
Assert.IsTrue(repeatedField.IsRepeated); |
||||
} |
||||
|
||||
[Test] |
||||
public void EnumDescriptor() |
||||
{ |
||||
// Note: this test is a bit different to the Java version because there's no static way of getting to the descriptor |
||||
EnumDescriptor enumType = UnittestProto3.Descriptor.FindTypeByName<EnumDescriptor>("ForeignEnum"); |
||||
EnumDescriptor nestedType = TestAllTypes.Descriptor.FindDescriptor<EnumDescriptor>("NestedEnum"); |
||||
|
||||
Assert.AreEqual("ForeignEnum", enumType.Name); |
||||
Assert.AreEqual("protobuf_unittest.ForeignEnum", enumType.FullName); |
||||
Assert.AreEqual(UnittestProto3.Descriptor, enumType.File); |
||||
Assert.Null(enumType.ContainingType); |
||||
Assert.Null(enumType.Proto.Options); |
||||
|
||||
Assert.AreEqual("NestedEnum", nestedType.Name); |
||||
Assert.AreEqual("protobuf_unittest.TestAllTypes.NestedEnum", |
||||
nestedType.FullName); |
||||
Assert.AreEqual(UnittestProto3.Descriptor, nestedType.File); |
||||
Assert.AreEqual(TestAllTypes.Descriptor, nestedType.ContainingType); |
||||
|
||||
EnumValueDescriptor value = enumType.FindValueByName("FOREIGN_FOO"); |
||||
Assert.AreEqual(value, enumType.Values[1]); |
||||
Assert.AreEqual("FOREIGN_FOO", value.Name); |
||||
Assert.AreEqual(4, value.Number); |
||||
Assert.AreEqual((int) ForeignEnum.FOREIGN_FOO, value.Number); |
||||
Assert.AreEqual(value, enumType.FindValueByNumber(4)); |
||||
Assert.Null(enumType.FindValueByName("NO_SUCH_VALUE")); |
||||
for (int i = 0; i < enumType.Values.Count; i++) |
||||
{ |
||||
Assert.AreEqual(i, enumType.Values[i].Index); |
||||
} |
||||
} |
||||
|
||||
[Test] |
||||
public void OneofDescriptor() |
||||
{ |
||||
OneofDescriptor descriptor = TestAllTypes.Descriptor.FindDescriptor<OneofDescriptor>("oneof_field"); |
||||
Assert.AreEqual("oneof_field", descriptor.Name); |
||||
Assert.AreEqual("protobuf_unittest.TestAllTypes.oneof_field", descriptor.FullName); |
||||
|
||||
var expectedFields = new[] { |
||||
TestAllTypes.OneofBytesFieldNumber, |
||||
TestAllTypes.OneofNestedMessageFieldNumber, |
||||
TestAllTypes.OneofStringFieldNumber, |
||||
TestAllTypes.OneofUint32FieldNumber } |
||||
.Select(fieldNumber => TestAllTypes.Descriptor.FindFieldByNumber(fieldNumber)) |
||||
.ToList(); |
||||
foreach (var field in expectedFields) |
||||
{ |
||||
Assert.AreSame(descriptor, field.ContainingOneof); |
||||
} |
||||
|
||||
CollectionAssert.AreEquivalent(expectedFields, descriptor.Fields); |
||||
} |
||||
} |
||||
} |
@ -1,84 +1,82 @@ |
||||
#region Copyright notice and license |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2008 Google Inc. All rights reserved. |
||||
// https://developers.google.com/protocol-buffers/ |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
#endregion |
||||
|
||||
using Google.Protobuf.DescriptorProtos; |
||||
|
||||
namespace Google.Protobuf.Descriptors |
||||
{ |
||||
/// <summary> |
||||
/// Base class for nearly all descriptors, providing common functionality. |
||||
/// </summary> |
||||
public abstract class DescriptorBase : IDescriptor |
||||
{ |
||||
private readonly FileDescriptor file; |
||||
private readonly string fullName; |
||||
private readonly int index; |
||||
|
||||
internal DescriptorBase(FileDescriptor file, string fullName, int index) |
||||
{ |
||||
this.file = file; |
||||
this.fullName = fullName; |
||||
this.index = index; |
||||
} |
||||
|
||||
/// <value> |
||||
/// The index of this descriptor within its parent descriptor. |
||||
/// </value> |
||||
/// <remarks> |
||||
/// This returns the index of this descriptor within its parent, for |
||||
/// this descriptor's type. (There can be duplicate values for different |
||||
/// types, e.g. one enum type with index 0 and one message type with index 0.) |
||||
/// </remarks> |
||||
public int Index |
||||
{ |
||||
get { return index; } |
||||
} |
||||
|
||||
public abstract string Name { get; } |
||||
|
||||
/// <summary> |
||||
/// The fully qualified name of the descriptor's target. |
||||
/// </summary> |
||||
public string FullName |
||||
{ |
||||
get { return fullName; } |
||||
} |
||||
|
||||
/// <value> |
||||
/// The file this descriptor was declared in. |
||||
/// </value> |
||||
public FileDescriptor File |
||||
{ |
||||
get { return file; } |
||||
} |
||||
} |
||||
#region Copyright notice and license |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2008 Google Inc. All rights reserved. |
||||
// https://developers.google.com/protocol-buffers/ |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
#endregion |
||||
|
||||
namespace Google.Protobuf.Reflection |
||||
{ |
||||
/// <summary> |
||||
/// Base class for nearly all descriptors, providing common functionality. |
||||
/// </summary> |
||||
public abstract class DescriptorBase : IDescriptor |
||||
{ |
||||
private readonly FileDescriptor file; |
||||
private readonly string fullName; |
||||
private readonly int index; |
||||
|
||||
internal DescriptorBase(FileDescriptor file, string fullName, int index) |
||||
{ |
||||
this.file = file; |
||||
this.fullName = fullName; |
||||
this.index = index; |
||||
} |
||||
|
||||
/// <value> |
||||
/// The index of this descriptor within its parent descriptor. |
||||
/// </value> |
||||
/// <remarks> |
||||
/// This returns the index of this descriptor within its parent, for |
||||
/// this descriptor's type. (There can be duplicate values for different |
||||
/// types, e.g. one enum type with index 0 and one message type with index 0.) |
||||
/// </remarks> |
||||
public int Index |
||||
{ |
||||
get { return index; } |
||||
} |
||||
|
||||
public abstract string Name { get; } |
||||
|
||||
/// <summary> |
||||
/// The fully qualified name of the descriptor's target. |
||||
/// </summary> |
||||
public string FullName |
||||
{ |
||||
get { return fullName; } |
||||
} |
||||
|
||||
/// <value> |
||||
/// The file this descriptor was declared in. |
||||
/// </value> |
||||
public FileDescriptor File |
||||
{ |
||||
get { return file; } |
||||
} |
||||
} |
||||
} |
@ -1,365 +1,365 @@ |
||||
#region Copyright notice and license |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2008 Google Inc. All rights reserved. |
||||
// https://developers.google.com/protocol-buffers/ |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
#endregion |
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Text; |
||||
using System.Text.RegularExpressions; |
||||
|
||||
namespace Google.Protobuf.Descriptors |
||||
{ |
||||
/// <summary> |
||||
/// Contains lookup tables containing all the descriptors defined in a particular file. |
||||
/// </summary> |
||||
internal sealed class DescriptorPool |
||||
{ |
||||
private readonly IDictionary<string, IDescriptor> descriptorsByName = |
||||
new Dictionary<string, IDescriptor>(); |
||||
|
||||
private readonly IDictionary<DescriptorIntPair, FieldDescriptor> fieldsByNumber = |
||||
new Dictionary<DescriptorIntPair, FieldDescriptor>(); |
||||
|
||||
private readonly IDictionary<DescriptorIntPair, EnumValueDescriptor> enumValuesByNumber = |
||||
new Dictionary<DescriptorIntPair, EnumValueDescriptor>(); |
||||
|
||||
private readonly HashSet<FileDescriptor> dependencies; |
||||
|
||||
internal DescriptorPool(FileDescriptor[] dependencyFiles) |
||||
{ |
||||
dependencies = new HashSet<FileDescriptor>(); |
||||
for (int i = 0; i < dependencyFiles.Length; i++) |
||||
{ |
||||
dependencies.Add(dependencyFiles[i]); |
||||
ImportPublicDependencies(dependencyFiles[i]); |
||||
} |
||||
|
||||
foreach (FileDescriptor dependency in dependencyFiles) |
||||
{ |
||||
AddPackage(dependency.Package, dependency); |
||||
} |
||||
} |
||||
|
||||
private void ImportPublicDependencies(FileDescriptor file) |
||||
{ |
||||
foreach (FileDescriptor dependency in file.PublicDependencies) |
||||
{ |
||||
if (dependencies.Add(dependency)) |
||||
{ |
||||
ImportPublicDependencies(dependency); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Finds a symbol of the given name within the pool. |
||||
/// </summary> |
||||
/// <typeparam name="T">The type of symbol to look for</typeparam> |
||||
/// <param name="fullName">Fully-qualified name to look up</param> |
||||
/// <returns>The symbol with the given name and type, |
||||
/// or null if the symbol doesn't exist or has the wrong type</returns> |
||||
internal T FindSymbol<T>(string fullName) where T : class
|
||||
{ |
||||
IDescriptor result; |
||||
descriptorsByName.TryGetValue(fullName, out result); |
||||
T descriptor = result as T; |
||||
if (descriptor != null) |
||||
{ |
||||
return descriptor; |
||||
} |
||||
|
||||
foreach (FileDescriptor dependency in dependencies) |
||||
{ |
||||
dependency.DescriptorPool.descriptorsByName.TryGetValue(fullName, out result); |
||||
descriptor = result as T; |
||||
if (descriptor != null) |
||||
{ |
||||
return descriptor; |
||||
} |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Adds a package to the symbol tables. If a package by the same name |
||||
/// already exists, that is fine, but if some other kind of symbol |
||||
/// exists under the same name, an exception is thrown. If the package |
||||
/// has multiple components, this also adds the parent package(s). |
||||
/// </summary> |
||||
internal void AddPackage(string fullName, FileDescriptor file) |
||||
{ |
||||
int dotpos = fullName.LastIndexOf('.'); |
||||
String name; |
||||
if (dotpos != -1) |
||||
{ |
||||
AddPackage(fullName.Substring(0, dotpos), file); |
||||
name = fullName.Substring(dotpos + 1); |
||||
} |
||||
else |
||||
{ |
||||
name = fullName; |
||||
} |
||||
|
||||
IDescriptor old; |
||||
if (descriptorsByName.TryGetValue(fullName, out old)) |
||||
{ |
||||
if (!(old is PackageDescriptor)) |
||||
{ |
||||
throw new DescriptorValidationException(file, |
||||
"\"" + name + |
||||
"\" is already defined (as something other than a " + |
||||
"package) in file \"" + old.File.Name + "\"."); |
||||
} |
||||
} |
||||
descriptorsByName[fullName] = new PackageDescriptor(name, fullName, file); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Adds a symbol to the symbol table. |
||||
/// </summary> |
||||
/// <exception cref="DescriptorValidationException">The symbol already existed |
||||
/// in the symbol table.</exception> |
||||
internal void AddSymbol(IDescriptor descriptor) |
||||
{ |
||||
ValidateSymbolName(descriptor); |
||||
String fullName = descriptor.FullName; |
||||
|
||||
IDescriptor old; |
||||
if (descriptorsByName.TryGetValue(fullName, out old)) |
||||
{ |
||||
int dotPos = fullName.LastIndexOf('.'); |
||||
string message; |
||||
if (descriptor.File == old.File) |
||||
{ |
||||
if (dotPos == -1) |
||||
{ |
||||
message = "\"" + fullName + "\" is already defined."; |
||||
} |
||||
else |
||||
{ |
||||
message = "\"" + fullName.Substring(dotPos + 1) + "\" is already defined in \"" + |
||||
fullName.Substring(0, dotPos) + "\"."; |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
message = "\"" + fullName + "\" is already defined in file \"" + old.File.Name + "\"."; |
||||
} |
||||
throw new DescriptorValidationException(descriptor, message); |
||||
} |
||||
descriptorsByName[fullName] = descriptor; |
||||
} |
||||
|
||||
private static readonly Regex ValidationRegex = new Regex("^[_A-Za-z][_A-Za-z0-9]*$", |
||||
FrameworkPortability.CompiledRegexWhereAvailable); |
||||
|
||||
/// <summary> |
||||
/// Verifies that the descriptor's name is valid (i.e. it contains |
||||
/// only letters, digits and underscores, and does not start with a digit). |
||||
/// </summary> |
||||
/// <param name="descriptor"></param> |
||||
private static void ValidateSymbolName(IDescriptor descriptor) |
||||
{ |
||||
if (descriptor.Name == "") |
||||
{ |
||||
throw new DescriptorValidationException(descriptor, "Missing name."); |
||||
} |
||||
if (!ValidationRegex.IsMatch(descriptor.Name)) |
||||
{ |
||||
throw new DescriptorValidationException(descriptor, |
||||
"\"" + descriptor.Name + "\" is not a valid identifier."); |
||||
} |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Returns the field with the given number in the given descriptor, |
||||
/// or null if it can't be found. |
||||
/// </summary> |
||||
internal FieldDescriptor FindFieldByNumber(MessageDescriptor messageDescriptor, int number) |
||||
{ |
||||
FieldDescriptor ret; |
||||
fieldsByNumber.TryGetValue(new DescriptorIntPair(messageDescriptor, number), out ret); |
||||
return ret; |
||||
} |
||||
|
||||
internal EnumValueDescriptor FindEnumValueByNumber(EnumDescriptor enumDescriptor, int number) |
||||
{ |
||||
EnumValueDescriptor ret; |
||||
enumValuesByNumber.TryGetValue(new DescriptorIntPair(enumDescriptor, number), out ret); |
||||
return ret; |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Adds a field to the fieldsByNumber table. |
||||
/// </summary> |
||||
/// <exception cref="DescriptorValidationException">A field with the same |
||||
/// containing type and number already exists.</exception> |
||||
internal void AddFieldByNumber(FieldDescriptor field) |
||||
{ |
||||
DescriptorIntPair key = new DescriptorIntPair(field.ContainingType, field.FieldNumber); |
||||
FieldDescriptor old; |
||||
if (fieldsByNumber.TryGetValue(key, out old)) |
||||
{ |
||||
throw new DescriptorValidationException(field, "Field number " + field.FieldNumber + |
||||
"has already been used in \"" + |
||||
field.ContainingType.FullName + |
||||
"\" by field \"" + old.Name + "\"."); |
||||
} |
||||
fieldsByNumber[key] = field; |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Adds an enum value to the enumValuesByNumber table. If an enum value |
||||
/// with the same type and number already exists, this method does nothing. |
||||
/// (This is allowed; the first value defined with the number takes precedence.) |
||||
/// </summary> |
||||
internal void AddEnumValueByNumber(EnumValueDescriptor enumValue) |
||||
{ |
||||
DescriptorIntPair key = new DescriptorIntPair(enumValue.EnumDescriptor, enumValue.Number); |
||||
if (!enumValuesByNumber.ContainsKey(key)) |
||||
{ |
||||
enumValuesByNumber[key] = enumValue; |
||||
} |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Looks up a descriptor by name, relative to some other descriptor. |
||||
/// The name may be fully-qualified (with a leading '.'), partially-qualified, |
||||
/// or unqualified. C++-like name lookup semantics are used to search for the |
||||
/// matching descriptor. |
||||
/// </summary> |
||||
internal IDescriptor LookupSymbol(string name, IDescriptor relativeTo) |
||||
{ |
||||
// TODO(jonskeet): This could be optimized in a number of ways. |
||||
|
||||
IDescriptor result; |
||||
if (name.StartsWith(".")) |
||||
{ |
||||
// Fully-qualified name. |
||||
result = FindSymbol<IDescriptor>(name.Substring(1)); |
||||
} |
||||
else |
||||
{ |
||||
// If "name" is a compound identifier, we want to search for the |
||||
// first component of it, then search within it for the rest. |
||||
int firstPartLength = name.IndexOf('.'); |
||||
string firstPart = firstPartLength == -1 ? name : name.Substring(0, firstPartLength); |
||||
|
||||
// We will search each parent scope of "relativeTo" looking for the |
||||
// symbol. |
||||
StringBuilder scopeToTry = new StringBuilder(relativeTo.FullName); |
||||
|
||||
while (true) |
||||
{ |
||||
// Chop off the last component of the scope. |
||||
|
||||
// TODO(jonskeet): Make this more efficient. May not be worth using StringBuilder at all |
||||
int dotpos = scopeToTry.ToString().LastIndexOf("."); |
||||
if (dotpos == -1) |
||||
{ |
||||
result = FindSymbol<IDescriptor>(name); |
||||
break; |
||||
} |
||||
else |
||||
{ |
||||
scopeToTry.Length = dotpos + 1; |
||||
|
||||
// Append firstPart and try to find. |
||||
scopeToTry.Append(firstPart); |
||||
result = FindSymbol<IDescriptor>(scopeToTry.ToString()); |
||||
|
||||
if (result != null) |
||||
{ |
||||
if (firstPartLength != -1) |
||||
{ |
||||
// We only found the first part of the symbol. Now look for |
||||
// the whole thing. If this fails, we *don't* want to keep |
||||
// searching parent scopes. |
||||
scopeToTry.Length = dotpos + 1; |
||||
scopeToTry.Append(name); |
||||
result = FindSymbol<IDescriptor>(scopeToTry.ToString()); |
||||
} |
||||
break; |
||||
} |
||||
|
||||
// Not found. Remove the name so we can try again. |
||||
scopeToTry.Length = dotpos; |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (result == null) |
||||
{ |
||||
throw new DescriptorValidationException(relativeTo, "\"" + name + "\" is not defined."); |
||||
} |
||||
else |
||||
{ |
||||
return result; |
||||
} |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Struct used to hold the keys for the fieldByNumber table. |
||||
/// </summary> |
||||
private struct DescriptorIntPair : IEquatable<DescriptorIntPair> |
||||
{ |
||||
private readonly int number; |
||||
private readonly IDescriptor descriptor; |
||||
|
||||
internal DescriptorIntPair(IDescriptor descriptor, int number) |
||||
{ |
||||
this.number = number; |
||||
this.descriptor = descriptor; |
||||
} |
||||
|
||||
public bool Equals(DescriptorIntPair other) |
||||
{ |
||||
return descriptor == other.descriptor |
||||
&& number == other.number; |
||||
} |
||||
|
||||
public override bool Equals(object obj) |
||||
{ |
||||
if (obj is DescriptorIntPair) |
||||
{ |
||||
return Equals((DescriptorIntPair) obj); |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
public override int GetHashCode() |
||||
{ |
||||
return descriptor.GetHashCode()*((1 << 16) - 1) + number; |
||||
} |
||||
} |
||||
} |
||||
#region Copyright notice and license |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2008 Google Inc. All rights reserved. |
||||
// https://developers.google.com/protocol-buffers/ |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
#endregion |
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Text; |
||||
using System.Text.RegularExpressions; |
||||
|
||||
namespace Google.Protobuf.Reflection |
||||
{ |
||||
/// <summary> |
||||
/// Contains lookup tables containing all the descriptors defined in a particular file. |
||||
/// </summary> |
||||
internal sealed class DescriptorPool |
||||
{ |
||||
private readonly IDictionary<string, IDescriptor> descriptorsByName = |
||||
new Dictionary<string, IDescriptor>(); |
||||
|
||||
private readonly IDictionary<DescriptorIntPair, FieldDescriptor> fieldsByNumber = |
||||
new Dictionary<DescriptorIntPair, FieldDescriptor>(); |
||||
|
||||
private readonly IDictionary<DescriptorIntPair, EnumValueDescriptor> enumValuesByNumber = |
||||
new Dictionary<DescriptorIntPair, EnumValueDescriptor>(); |
||||
|
||||
private readonly HashSet<FileDescriptor> dependencies; |
||||
|
||||
internal DescriptorPool(FileDescriptor[] dependencyFiles) |
||||
{ |
||||
dependencies = new HashSet<FileDescriptor>(); |
||||
for (int i = 0; i < dependencyFiles.Length; i++) |
||||
{ |
||||
dependencies.Add(dependencyFiles[i]); |
||||
ImportPublicDependencies(dependencyFiles[i]); |
||||
} |
||||
|
||||
foreach (FileDescriptor dependency in dependencyFiles) |
||||
{ |
||||
AddPackage(dependency.Package, dependency); |
||||
} |
||||
} |
||||
|
||||
private void ImportPublicDependencies(FileDescriptor file) |
||||
{ |
||||
foreach (FileDescriptor dependency in file.PublicDependencies) |
||||
{ |
||||
if (dependencies.Add(dependency)) |
||||
{ |
||||
ImportPublicDependencies(dependency); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Finds a symbol of the given name within the pool. |
||||
/// </summary> |
||||
/// <typeparam name="T">The type of symbol to look for</typeparam> |
||||
/// <param name="fullName">Fully-qualified name to look up</param> |
||||
/// <returns>The symbol with the given name and type, |
||||
/// or null if the symbol doesn't exist or has the wrong type</returns> |
||||
internal T FindSymbol<T>(string fullName) where T : class
|
||||
{ |
||||
IDescriptor result; |
||||
descriptorsByName.TryGetValue(fullName, out result); |
||||
T descriptor = result as T; |
||||
if (descriptor != null) |
||||
{ |
||||
return descriptor; |
||||
} |
||||
|
||||
foreach (FileDescriptor dependency in dependencies) |
||||
{ |
||||
dependency.DescriptorPool.descriptorsByName.TryGetValue(fullName, out result); |
||||
descriptor = result as T; |
||||
if (descriptor != null) |
||||
{ |
||||
return descriptor; |
||||
} |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Adds a package to the symbol tables. If a package by the same name |
||||
/// already exists, that is fine, but if some other kind of symbol |
||||
/// exists under the same name, an exception is thrown. If the package |
||||
/// has multiple components, this also adds the parent package(s). |
||||
/// </summary> |
||||
internal void AddPackage(string fullName, FileDescriptor file) |
||||
{ |
||||
int dotpos = fullName.LastIndexOf('.'); |
||||
String name; |
||||
if (dotpos != -1) |
||||
{ |
||||
AddPackage(fullName.Substring(0, dotpos), file); |
||||
name = fullName.Substring(dotpos + 1); |
||||
} |
||||
else |
||||
{ |
||||
name = fullName; |
||||
} |
||||
|
||||
IDescriptor old; |
||||
if (descriptorsByName.TryGetValue(fullName, out old)) |
||||
{ |
||||
if (!(old is PackageDescriptor)) |
||||
{ |
||||
throw new DescriptorValidationException(file, |
||||
"\"" + name + |
||||
"\" is already defined (as something other than a " + |
||||
"package) in file \"" + old.File.Name + "\"."); |
||||
} |
||||
} |
||||
descriptorsByName[fullName] = new PackageDescriptor(name, fullName, file); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Adds a symbol to the symbol table. |
||||
/// </summary> |
||||
/// <exception cref="DescriptorValidationException">The symbol already existed |
||||
/// in the symbol table.</exception> |
||||
internal void AddSymbol(IDescriptor descriptor) |
||||
{ |
||||
ValidateSymbolName(descriptor); |
||||
String fullName = descriptor.FullName; |
||||
|
||||
IDescriptor old; |
||||
if (descriptorsByName.TryGetValue(fullName, out old)) |
||||
{ |
||||
int dotPos = fullName.LastIndexOf('.'); |
||||
string message; |
||||
if (descriptor.File == old.File) |
||||
{ |
||||
if (dotPos == -1) |
||||
{ |
||||
message = "\"" + fullName + "\" is already defined."; |
||||
} |
||||
else |
||||
{ |
||||
message = "\"" + fullName.Substring(dotPos + 1) + "\" is already defined in \"" + |
||||
fullName.Substring(0, dotPos) + "\"."; |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
message = "\"" + fullName + "\" is already defined in file \"" + old.File.Name + "\"."; |
||||
} |
||||
throw new DescriptorValidationException(descriptor, message); |
||||
} |
||||
descriptorsByName[fullName] = descriptor; |
||||
} |
||||
|
||||
private static readonly Regex ValidationRegex = new Regex("^[_A-Za-z][_A-Za-z0-9]*$", |
||||
FrameworkPortability.CompiledRegexWhereAvailable); |
||||
|
||||
/// <summary> |
||||
/// Verifies that the descriptor's name is valid (i.e. it contains |
||||
/// only letters, digits and underscores, and does not start with a digit). |
||||
/// </summary> |
||||
/// <param name="descriptor"></param> |
||||
private static void ValidateSymbolName(IDescriptor descriptor) |
||||
{ |
||||
if (descriptor.Name == "") |
||||
{ |
||||
throw new DescriptorValidationException(descriptor, "Missing name."); |
||||
} |
||||
if (!ValidationRegex.IsMatch(descriptor.Name)) |
||||
{ |
||||
throw new DescriptorValidationException(descriptor, |
||||
"\"" + descriptor.Name + "\" is not a valid identifier."); |
||||
} |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Returns the field with the given number in the given descriptor, |
||||
/// or null if it can't be found. |
||||
/// </summary> |
||||
internal FieldDescriptor FindFieldByNumber(MessageDescriptor messageDescriptor, int number) |
||||
{ |
||||
FieldDescriptor ret; |
||||
fieldsByNumber.TryGetValue(new DescriptorIntPair(messageDescriptor, number), out ret); |
||||
return ret; |
||||
} |
||||
|
||||
internal EnumValueDescriptor FindEnumValueByNumber(EnumDescriptor enumDescriptor, int number) |
||||
{ |
||||
EnumValueDescriptor ret; |
||||
enumValuesByNumber.TryGetValue(new DescriptorIntPair(enumDescriptor, number), out ret); |
||||
return ret; |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Adds a field to the fieldsByNumber table. |
||||
/// </summary> |
||||
/// <exception cref="DescriptorValidationException">A field with the same |
||||
/// containing type and number already exists.</exception> |
||||
internal void AddFieldByNumber(FieldDescriptor field) |
||||
{ |
||||
DescriptorIntPair key = new DescriptorIntPair(field.ContainingType, field.FieldNumber); |
||||
FieldDescriptor old; |
||||
if (fieldsByNumber.TryGetValue(key, out old)) |
||||
{ |
||||
throw new DescriptorValidationException(field, "Field number " + field.FieldNumber + |
||||
"has already been used in \"" + |
||||
field.ContainingType.FullName + |
||||
"\" by field \"" + old.Name + "\"."); |
||||
} |
||||
fieldsByNumber[key] = field; |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Adds an enum value to the enumValuesByNumber table. If an enum value |
||||
/// with the same type and number already exists, this method does nothing. |
||||
/// (This is allowed; the first value defined with the number takes precedence.) |
||||
/// </summary> |
||||
internal void AddEnumValueByNumber(EnumValueDescriptor enumValue) |
||||
{ |
||||
DescriptorIntPair key = new DescriptorIntPair(enumValue.EnumDescriptor, enumValue.Number); |
||||
if (!enumValuesByNumber.ContainsKey(key)) |
||||
{ |
||||
enumValuesByNumber[key] = enumValue; |
||||
} |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Looks up a descriptor by name, relative to some other descriptor. |
||||
/// The name may be fully-qualified (with a leading '.'), partially-qualified, |
||||
/// or unqualified. C++-like name lookup semantics are used to search for the |
||||
/// matching descriptor. |
||||
/// </summary> |
||||
internal IDescriptor LookupSymbol(string name, IDescriptor relativeTo) |
||||
{ |
||||
// TODO(jonskeet): This could be optimized in a number of ways. |
||||
|
||||
IDescriptor result; |
||||
if (name.StartsWith(".")) |
||||
{ |
||||
// Fully-qualified name. |
||||
result = FindSymbol<IDescriptor>(name.Substring(1)); |
||||
} |
||||
else |
||||
{ |
||||
// If "name" is a compound identifier, we want to search for the |
||||
// first component of it, then search within it for the rest. |
||||
int firstPartLength = name.IndexOf('.'); |
||||
string firstPart = firstPartLength == -1 ? name : name.Substring(0, firstPartLength); |
||||
|
||||
// We will search each parent scope of "relativeTo" looking for the |
||||
// symbol. |
||||
StringBuilder scopeToTry = new StringBuilder(relativeTo.FullName); |
||||
|
||||
while (true) |
||||
{ |
||||
// Chop off the last component of the scope. |
||||
|
||||
// TODO(jonskeet): Make this more efficient. May not be worth using StringBuilder at all |
||||
int dotpos = scopeToTry.ToString().LastIndexOf("."); |
||||
if (dotpos == -1) |
||||
{ |
||||
result = FindSymbol<IDescriptor>(name); |
||||
break; |
||||
} |
||||
else |
||||
{ |
||||
scopeToTry.Length = dotpos + 1; |
||||
|
||||
// Append firstPart and try to find. |
||||
scopeToTry.Append(firstPart); |
||||
result = FindSymbol<IDescriptor>(scopeToTry.ToString()); |
||||
|
||||
if (result != null) |
||||
{ |
||||
if (firstPartLength != -1) |
||||
{ |
||||
// We only found the first part of the symbol. Now look for |
||||
// the whole thing. If this fails, we *don't* want to keep |
||||
// searching parent scopes. |
||||
scopeToTry.Length = dotpos + 1; |
||||
scopeToTry.Append(name); |
||||
result = FindSymbol<IDescriptor>(scopeToTry.ToString()); |
||||
} |
||||
break; |
||||
} |
||||
|
||||
// Not found. Remove the name so we can try again. |
||||
scopeToTry.Length = dotpos; |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (result == null) |
||||
{ |
||||
throw new DescriptorValidationException(relativeTo, "\"" + name + "\" is not defined."); |
||||
} |
||||
else |
||||
{ |
||||
return result; |
||||
} |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Struct used to hold the keys for the fieldByNumber table. |
||||
/// </summary> |
||||
private struct DescriptorIntPair : IEquatable<DescriptorIntPair> |
||||
{ |
||||
private readonly int number; |
||||
private readonly IDescriptor descriptor; |
||||
|
||||
internal DescriptorIntPair(IDescriptor descriptor, int number) |
||||
{ |
||||
this.number = number; |
||||
this.descriptor = descriptor; |
||||
} |
||||
|
||||
public bool Equals(DescriptorIntPair other) |
||||
{ |
||||
return descriptor == other.descriptor |
||||
&& number == other.number; |
||||
} |
||||
|
||||
public override bool Equals(object obj) |
||||
{ |
||||
if (obj is DescriptorIntPair) |
||||
{ |
||||
return Equals((DescriptorIntPair) obj); |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
public override int GetHashCode() |
||||
{ |
||||
return descriptor.GetHashCode()*((1 << 16) - 1) + number; |
||||
} |
||||
} |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -1,65 +1,65 @@ |
||||
#region Copyright notice and license |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2008 Google Inc. All rights reserved. |
||||
// https://developers.google.com/protocol-buffers/ |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
#endregion |
||||
|
||||
using System.Collections.Generic; |
||||
using System.Collections.ObjectModel; |
||||
|
||||
namespace Google.Protobuf.Descriptors |
||||
{ |
||||
/// <summary> |
||||
/// Internal class containing utility methods when working with descriptors. |
||||
/// </summary> |
||||
internal static class DescriptorUtil |
||||
{ |
||||
/// <summary> |
||||
/// Equivalent to Func[TInput, int, TOutput] but usable in .NET 2.0. Only used to convert |
||||
/// arrays. |
||||
/// </summary> |
||||
internal delegate TOutput IndexedConverter<TInput, TOutput>(TInput element, int index); |
||||
|
||||
/// <summary> |
||||
/// Converts the given array into a read-only list, applying the specified conversion to |
||||
/// each input element. |
||||
/// </summary> |
||||
internal static IList<TOutput> ConvertAndMakeReadOnly<TInput, TOutput>(IList<TInput> input, |
||||
IndexedConverter<TInput, TOutput> |
||||
converter) |
||||
{ |
||||
TOutput[] array = new TOutput[input.Count]; |
||||
for (int i = 0; i < array.Length; i++) |
||||
{ |
||||
array[i] = converter(input[i], i); |
||||
} |
||||
return new ReadOnlyCollection<TOutput>(array); |
||||
} |
||||
} |
||||
#region Copyright notice and license |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2008 Google Inc. All rights reserved. |
||||
// https://developers.google.com/protocol-buffers/ |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
#endregion |
||||
|
||||
using System.Collections.Generic; |
||||
using System.Collections.ObjectModel; |
||||
|
||||
namespace Google.Protobuf.Reflection |
||||
{ |
||||
/// <summary> |
||||
/// Internal class containing utility methods when working with descriptors. |
||||
/// </summary> |
||||
internal static class DescriptorUtil |
||||
{ |
||||
/// <summary> |
||||
/// Equivalent to Func[TInput, int, TOutput] but usable in .NET 2.0. Only used to convert |
||||
/// arrays. |
||||
/// </summary> |
||||
internal delegate TOutput IndexedConverter<TInput, TOutput>(TInput element, int index); |
||||
|
||||
/// <summary> |
||||
/// Converts the given array into a read-only list, applying the specified conversion to |
||||
/// each input element. |
||||
/// </summary> |
||||
internal static IList<TOutput> ConvertAndMakeReadOnly<TInput, TOutput>(IList<TInput> input, |
||||
IndexedConverter<TInput, TOutput> |
||||
converter) |
||||
{ |
||||
TOutput[] array = new TOutput[input.Count]; |
||||
for (int i = 0; i < array.Length; i++) |
||||
{ |
||||
array[i] = converter(input[i], i); |
||||
} |
||||
return new ReadOnlyCollection<TOutput>(array); |
||||
} |
||||
} |
||||
} |
@ -1,80 +1,80 @@ |
||||
#region Copyright notice and license |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2008 Google Inc. All rights reserved. |
||||
// https://developers.google.com/protocol-buffers/ |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
#endregion |
||||
|
||||
using System; |
||||
|
||||
namespace Google.Protobuf.Descriptors |
||||
{ |
||||
/// <summary> |
||||
/// Thrown when building descriptors fails because the source DescriptorProtos |
||||
/// are not valid. |
||||
/// </summary> |
||||
public sealed class DescriptorValidationException : Exception |
||||
{ |
||||
private readonly String name; |
||||
private readonly string description; |
||||
|
||||
/// <value> |
||||
/// The full name of the descriptor where the error occurred. |
||||
/// </value> |
||||
public String ProblemSymbolName |
||||
{ |
||||
get { return name; } |
||||
} |
||||
|
||||
/// <value> |
||||
/// A human-readable description of the error. (The Message property |
||||
/// is made up of the descriptor's name and this description.) |
||||
/// </value> |
||||
public string Description |
||||
{ |
||||
get { return description; } |
||||
} |
||||
|
||||
internal DescriptorValidationException(IDescriptor problemDescriptor, string description) : |
||||
base(problemDescriptor.FullName + ": " + description) |
||||
{ |
||||
// Note that problemDescriptor may be partially uninitialized, so we |
||||
// don't want to expose it directly to the user. So, we only provide |
||||
// the name and the original proto. |
||||
name = problemDescriptor.FullName; |
||||
this.description = description; |
||||
} |
||||
|
||||
internal DescriptorValidationException(IDescriptor problemDescriptor, string description, Exception cause) : |
||||
base(problemDescriptor.FullName + ": " + description, cause) |
||||
{ |
||||
name = problemDescriptor.FullName; |
||||
this.description = description; |
||||
} |
||||
} |
||||
#region Copyright notice and license |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2008 Google Inc. All rights reserved. |
||||
// https://developers.google.com/protocol-buffers/ |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
#endregion |
||||
|
||||
using System; |
||||
|
||||
namespace Google.Protobuf.Reflection |
||||
{ |
||||
/// <summary> |
||||
/// Thrown when building descriptors fails because the source DescriptorProtos |
||||
/// are not valid. |
||||
/// </summary> |
||||
public sealed class DescriptorValidationException : Exception |
||||
{ |
||||
private readonly String name; |
||||
private readonly string description; |
||||
|
||||
/// <value> |
||||
/// The full name of the descriptor where the error occurred. |
||||
/// </value> |
||||
public String ProblemSymbolName |
||||
{ |
||||
get { return name; } |
||||
} |
||||
|
||||
/// <value> |
||||
/// A human-readable description of the error. (The Message property |
||||
/// is made up of the descriptor's name and this description.) |
||||
/// </value> |
||||
public string Description |
||||
{ |
||||
get { return description; } |
||||
} |
||||
|
||||
internal DescriptorValidationException(IDescriptor problemDescriptor, string description) : |
||||
base(problemDescriptor.FullName + ": " + description) |
||||
{ |
||||
// Note that problemDescriptor may be partially uninitialized, so we |
||||
// don't want to expose it directly to the user. So, we only provide |
||||
// the name and the original proto. |
||||
name = problemDescriptor.FullName; |
||||
this.description = description; |
||||
} |
||||
|
||||
internal DescriptorValidationException(IDescriptor problemDescriptor, string description, Exception cause) : |
||||
base(problemDescriptor.FullName + ": " + description, cause) |
||||
{ |
||||
name = problemDescriptor.FullName; |
||||
this.description = description; |
||||
} |
||||
} |
||||
} |
@ -1,109 +1,108 @@ |
||||
#region Copyright notice and license |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2008 Google Inc. All rights reserved. |
||||
// https://developers.google.com/protocol-buffers/ |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
#endregion |
||||
|
||||
using System.Collections.Generic; |
||||
using Google.Protobuf.DescriptorProtos; |
||||
|
||||
namespace Google.Protobuf.Descriptors |
||||
{ |
||||
/// <summary> |
||||
/// Descriptor for an enum type in a .proto file. |
||||
/// </summary> |
||||
public sealed class EnumDescriptor : DescriptorBase |
||||
{ |
||||
private readonly EnumDescriptorProto proto; |
||||
private readonly MessageDescriptor containingType; |
||||
private readonly IList<EnumValueDescriptor> values; |
||||
|
||||
internal EnumDescriptor(EnumDescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int index) |
||||
: base(file, file.ComputeFullName(parent, proto.Name), index) |
||||
{ |
||||
this.proto = proto; |
||||
containingType = parent; |
||||
|
||||
if (proto.Value.Count == 0) |
||||
{ |
||||
// We cannot allow enums with no values because this would mean there |
||||
// would be no valid default value for fields of this type. |
||||
throw new DescriptorValidationException(this, "Enums must contain at least one value."); |
||||
} |
||||
|
||||
values = DescriptorUtil.ConvertAndMakeReadOnly(proto.Value, |
||||
(value, i) => new EnumValueDescriptor(value, file, this, i)); |
||||
|
||||
File.DescriptorPool.AddSymbol(this); |
||||
} |
||||
|
||||
internal EnumDescriptorProto Proto { get { return proto; } } |
||||
|
||||
/// <summary> |
||||
/// The brief name of the descriptor's target. |
||||
/// </summary> |
||||
public override string Name { get { return proto.Name; } } |
||||
|
||||
/// <value> |
||||
/// If this is a nested type, get the outer descriptor, otherwise null. |
||||
/// </value> |
||||
public MessageDescriptor ContainingType |
||||
{ |
||||
get { return containingType; } |
||||
} |
||||
|
||||
/// <value> |
||||
/// An unmodifiable list of defined value descriptors for this enum. |
||||
/// </value> |
||||
public IList<EnumValueDescriptor> Values |
||||
{ |
||||
get { return values; } |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Finds an enum value by number. If multiple enum values have the |
||||
/// same number, this returns the first defined value with that number. |
||||
/// If there is no value for the given number, this returns <c>null</c>. |
||||
/// </summary> |
||||
public EnumValueDescriptor FindValueByNumber(int number) |
||||
{ |
||||
return File.DescriptorPool.FindEnumValueByNumber(this, number); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Finds an enum value by name. |
||||
/// </summary> |
||||
/// <param name="name">The unqualified name of the value (e.g. "FOO").</param> |
||||
/// <returns>The value's descriptor, or null if not found.</returns> |
||||
public EnumValueDescriptor FindValueByName(string name) |
||||
{ |
||||
return File.DescriptorPool.FindSymbol<EnumValueDescriptor>(FullName + "." + name); |
||||
} |
||||
} |
||||
#region Copyright notice and license |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2008 Google Inc. All rights reserved. |
||||
// https://developers.google.com/protocol-buffers/ |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
#endregion |
||||
|
||||
using System.Collections.Generic; |
||||
|
||||
namespace Google.Protobuf.Reflection |
||||
{ |
||||
/// <summary> |
||||
/// Descriptor for an enum type in a .proto file. |
||||
/// </summary> |
||||
public sealed class EnumDescriptor : DescriptorBase |
||||
{ |
||||
private readonly EnumDescriptorProto proto; |
||||
private readonly MessageDescriptor containingType; |
||||
private readonly IList<EnumValueDescriptor> values; |
||||
|
||||
internal EnumDescriptor(EnumDescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int index) |
||||
: base(file, file.ComputeFullName(parent, proto.Name), index) |
||||
{ |
||||
this.proto = proto; |
||||
containingType = parent; |
||||
|
||||
if (proto.Value.Count == 0) |
||||
{ |
||||
// We cannot allow enums with no values because this would mean there |
||||
// would be no valid default value for fields of this type. |
||||
throw new DescriptorValidationException(this, "Enums must contain at least one value."); |
||||
} |
||||
|
||||
values = DescriptorUtil.ConvertAndMakeReadOnly(proto.Value, |
||||
(value, i) => new EnumValueDescriptor(value, file, this, i)); |
||||
|
||||
File.DescriptorPool.AddSymbol(this); |
||||
} |
||||
|
||||
internal EnumDescriptorProto Proto { get { return proto; } } |
||||
|
||||
/// <summary> |
||||
/// The brief name of the descriptor's target. |
||||
/// </summary> |
||||
public override string Name { get { return proto.Name; } } |
||||
|
||||
/// <value> |
||||
/// If this is a nested type, get the outer descriptor, otherwise null. |
||||
/// </value> |
||||
public MessageDescriptor ContainingType |
||||
{ |
||||
get { return containingType; } |
||||
} |
||||
|
||||
/// <value> |
||||
/// An unmodifiable list of defined value descriptors for this enum. |
||||
/// </value> |
||||
public IList<EnumValueDescriptor> Values |
||||
{ |
||||
get { return values; } |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Finds an enum value by number. If multiple enum values have the |
||||
/// same number, this returns the first defined value with that number. |
||||
/// If there is no value for the given number, this returns <c>null</c>. |
||||
/// </summary> |
||||
public EnumValueDescriptor FindValueByNumber(int number) |
||||
{ |
||||
return File.DescriptorPool.FindEnumValueByNumber(this, number); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Finds an enum value by name. |
||||
/// </summary> |
||||
/// <param name="name">The unqualified name of the value (e.g. "FOO").</param> |
||||
/// <returns>The value's descriptor, or null if not found.</returns> |
||||
public EnumValueDescriptor FindValueByName(string name) |
||||
{ |
||||
return File.DescriptorPool.FindSymbol<EnumValueDescriptor>(FullName + "." + name); |
||||
} |
||||
} |
||||
} |
@ -1,63 +1,61 @@ |
||||
#region Copyright notice and license |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2008 Google Inc. All rights reserved. |
||||
// https://developers.google.com/protocol-buffers/ |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
#endregion |
||||
|
||||
using Google.Protobuf.DescriptorProtos; |
||||
|
||||
namespace Google.Protobuf.Descriptors |
||||
{ |
||||
/// <summary> |
||||
/// Descriptor for a single enum value within an enum in a .proto file. |
||||
/// </summary> |
||||
public sealed class EnumValueDescriptor : DescriptorBase |
||||
{ |
||||
private readonly EnumDescriptor enumDescriptor; |
||||
private readonly EnumValueDescriptorProto proto; |
||||
|
||||
internal EnumValueDescriptor(EnumValueDescriptorProto proto, FileDescriptor file, |
||||
EnumDescriptor parent, int index) |
||||
: base(file, parent.FullName + "." + proto.Name, index) |
||||
{ |
||||
this.proto = proto; |
||||
enumDescriptor = parent; |
||||
file.DescriptorPool.AddSymbol(this); |
||||
file.DescriptorPool.AddEnumValueByNumber(this); |
||||
} |
||||
|
||||
internal EnumValueDescriptorProto Proto { get { return proto; } } |
||||
|
||||
public override string Name { get { return proto.Name; } } |
||||
|
||||
public int Number { get { return Proto.Number; } } |
||||
|
||||
public EnumDescriptor EnumDescriptor { get { return enumDescriptor; } } |
||||
} |
||||
#region Copyright notice and license |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2008 Google Inc. All rights reserved. |
||||
// https://developers.google.com/protocol-buffers/ |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
#endregion |
||||
|
||||
namespace Google.Protobuf.Reflection |
||||
{ |
||||
/// <summary> |
||||
/// Descriptor for a single enum value within an enum in a .proto file. |
||||
/// </summary> |
||||
public sealed class EnumValueDescriptor : DescriptorBase |
||||
{ |
||||
private readonly EnumDescriptor enumDescriptor; |
||||
private readonly EnumValueDescriptorProto proto; |
||||
|
||||
internal EnumValueDescriptor(EnumValueDescriptorProto proto, FileDescriptor file, |
||||
EnumDescriptor parent, int index) |
||||
: base(file, parent.FullName + "." + proto.Name, index) |
||||
{ |
||||
this.proto = proto; |
||||
enumDescriptor = parent; |
||||
file.DescriptorPool.AddSymbol(this); |
||||
file.DescriptorPool.AddEnumValueByNumber(this); |
||||
} |
||||
|
||||
internal EnumValueDescriptorProto Proto { get { return proto; } } |
||||
|
||||
public override string Name { get { return proto.Name; } } |
||||
|
||||
public int Number { get { return Proto.Number; } } |
||||
|
||||
public EnumDescriptor EnumDescriptor { get { return enumDescriptor; } } |
||||
} |
||||
} |
@ -1,98 +1,97 @@ |
||||
#region Copyright notice and license |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2008 Google Inc. All rights reserved. |
||||
// https://developers.google.com/protocol-buffers/ |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
#endregion |
||||
|
||||
using System; |
||||
using System.Collections.ObjectModel; |
||||
using Google.Protobuf.Descriptors; |
||||
|
||||
namespace Google.Protobuf.FieldAccess |
||||
{ |
||||
/// <summary> |
||||
/// Provides access to fields in generated messages via reflection. |
||||
/// </summary> |
||||
public sealed class FieldAccessorTable |
||||
{ |
||||
private readonly ReadOnlyCollection<IFieldAccessor> accessors; |
||||
private readonly ReadOnlyCollection<OneofAccessor> oneofs; |
||||
private readonly MessageDescriptor descriptor; |
||||
|
||||
/// <summary> |
||||
/// Constructs a FieldAccessorTable for a particular message class. |
||||
/// Only one FieldAccessorTable should be constructed per class. |
||||
/// </summary> |
||||
/// <param name="type">The CLR type for the message.</param> |
||||
/// <param name="descriptor">The type's descriptor</param> |
||||
/// <param name="propertyNames">The Pascal-case names of all the field-based properties in the message.</param> |
||||
public FieldAccessorTable(Type type, MessageDescriptor descriptor, string[] propertyNames, string[] oneofPropertyNames) |
||||
{ |
||||
this.descriptor = descriptor; |
||||
var accessorsArray = new IFieldAccessor[descriptor.Fields.Count]; |
||||
for (int i = 0; i < accessorsArray.Length; i++) |
||||
{ |
||||
var field = descriptor.Fields[i]; |
||||
var name = propertyNames[i]; |
||||
accessorsArray[i] = |
||||
field.IsMap ? new MapFieldAccessor(type, name, field) |
||||
: field.IsRepeated ? new RepeatedFieldAccessor(type, name, field) |
||||
: (IFieldAccessor) new SingleFieldAccessor(type, name, field); |
||||
} |
||||
accessors = new ReadOnlyCollection<IFieldAccessor>(accessorsArray); |
||||
var oneofsArray = new OneofAccessor[descriptor.Oneofs.Count]; |
||||
for (int i = 0; i < oneofsArray.Length; i++) |
||||
{ |
||||
var oneof = descriptor.Oneofs[i]; |
||||
oneofsArray[i] = new OneofAccessor(type, oneofPropertyNames[i], oneof); |
||||
} |
||||
oneofs = new ReadOnlyCollection<OneofAccessor>(oneofsArray); |
||||
} |
||||
|
||||
// TODO: Validate the name here... should possibly make this type a more "general reflection access" type, |
||||
// bearing in mind the oneof parts to come as well. |
||||
/// <summary> |
||||
/// Returns all of the field accessors for the message type. |
||||
/// </summary> |
||||
public ReadOnlyCollection<IFieldAccessor> Accessors { get { return accessors; } } |
||||
|
||||
public ReadOnlyCollection<OneofAccessor> Oneofs { get { return oneofs; } } |
||||
|
||||
// TODO: Review this, as it's easy to get confused between FieldNumber and Index. |
||||
// Currently only used to get an accessor related to a oneof... maybe just make that simpler? |
||||
public IFieldAccessor this[int fieldNumber] |
||||
{ |
||||
get |
||||
{ |
||||
FieldDescriptor field = descriptor.FindFieldByNumber(fieldNumber); |
||||
return accessors[field.Index]; |
||||
} |
||||
} |
||||
} |
||||
#region Copyright notice and license |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2008 Google Inc. All rights reserved. |
||||
// https://developers.google.com/protocol-buffers/ |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
#endregion |
||||
|
||||
using System; |
||||
using System.Collections.ObjectModel; |
||||
|
||||
namespace Google.Protobuf.Reflection |
||||
{ |
||||
/// <summary> |
||||
/// Provides access to fields in generated messages via reflection. |
||||
/// </summary> |
||||
public sealed class FieldAccessorTable |
||||
{ |
||||
private readonly ReadOnlyCollection<IFieldAccessor> accessors; |
||||
private readonly ReadOnlyCollection<OneofAccessor> oneofs; |
||||
private readonly MessageDescriptor descriptor; |
||||
|
||||
/// <summary> |
||||
/// Constructs a FieldAccessorTable for a particular message class. |
||||
/// Only one FieldAccessorTable should be constructed per class. |
||||
/// </summary> |
||||
/// <param name="type">The CLR type for the message.</param> |
||||
/// <param name="descriptor">The type's descriptor</param> |
||||
/// <param name="propertyNames">The Pascal-case names of all the field-based properties in the message.</param> |
||||
public FieldAccessorTable(Type type, MessageDescriptor descriptor, string[] propertyNames, string[] oneofPropertyNames) |
||||
{ |
||||
this.descriptor = descriptor; |
||||
var accessorsArray = new IFieldAccessor[descriptor.Fields.Count]; |
||||
for (int i = 0; i < accessorsArray.Length; i++) |
||||
{ |
||||
var field = descriptor.Fields[i]; |
||||
var name = propertyNames[i]; |
||||
accessorsArray[i] = |
||||
field.IsMap ? new MapFieldAccessor(type, name, field) |
||||
: field.IsRepeated ? new RepeatedFieldAccessor(type, name, field) |
||||
: (IFieldAccessor) new SingleFieldAccessor(type, name, field); |
||||
} |
||||
accessors = new ReadOnlyCollection<IFieldAccessor>(accessorsArray); |
||||
var oneofsArray = new OneofAccessor[descriptor.Oneofs.Count]; |
||||
for (int i = 0; i < oneofsArray.Length; i++) |
||||
{ |
||||
var oneof = descriptor.Oneofs[i]; |
||||
oneofsArray[i] = new OneofAccessor(type, oneofPropertyNames[i], oneof); |
||||
} |
||||
oneofs = new ReadOnlyCollection<OneofAccessor>(oneofsArray); |
||||
} |
||||
|
||||
// TODO: Validate the name here... should possibly make this type a more "general reflection access" type, |
||||
// bearing in mind the oneof parts to come as well. |
||||
/// <summary> |
||||
/// Returns all of the field accessors for the message type. |
||||
/// </summary> |
||||
public ReadOnlyCollection<IFieldAccessor> Accessors { get { return accessors; } } |
||||
|
||||
public ReadOnlyCollection<OneofAccessor> Oneofs { get { return oneofs; } } |
||||
|
||||
// TODO: Review this, as it's easy to get confused between FieldNumber and Index. |
||||
// Currently only used to get an accessor related to a oneof... maybe just make that simpler? |
||||
public IFieldAccessor this[int fieldNumber] |
||||
{ |
||||
get |
||||
{ |
||||
FieldDescriptor field = descriptor.FindFieldByNumber(fieldNumber); |
||||
return accessors[field.Index]; |
||||
} |
||||
} |
||||
} |
||||
} |
@ -1,293 +1,292 @@ |
||||
#region Copyright notice and license |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2008 Google Inc. All rights reserved. |
||||
// https://developers.google.com/protocol-buffers/ |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
#endregion |
||||
|
||||
using System; |
||||
using Google.Protobuf.DescriptorProtos; |
||||
|
||||
namespace Google.Protobuf.Descriptors |
||||
{ |
||||
/// <summary> |
||||
/// Descriptor for a field or extension within a message in a .proto file. |
||||
/// </summary> |
||||
public sealed class FieldDescriptor : DescriptorBase, IComparable<FieldDescriptor> |
||||
{ |
||||
private readonly FieldDescriptorProto proto; |
||||
private EnumDescriptor enumType; |
||||
private MessageDescriptor messageType; |
||||
private readonly MessageDescriptor containingType; |
||||
private readonly OneofDescriptor containingOneof; |
||||
private FieldType fieldType; |
||||
|
||||
internal FieldDescriptor(FieldDescriptorProto proto, FileDescriptor file, |
||||
MessageDescriptor parent, int index) |
||||
: base(file, file.ComputeFullName(parent, proto.Name), index) |
||||
{ |
||||
this.proto = proto; |
||||
if (proto.Type != 0) |
||||
{ |
||||
fieldType = GetFieldTypeFromProtoType(proto.Type); |
||||
} |
||||
|
||||
if (FieldNumber <= 0) |
||||
{ |
||||
throw new DescriptorValidationException(this, |
||||
"Field numbers must be positive integers."); |
||||
} |
||||
containingType = parent; |
||||
// OneofIndex "defaults" to -1 due to a hack in FieldDescriptor.OnConstruction. |
||||
if (proto.OneofIndex != -1) |
||||
{ |
||||
if (proto.OneofIndex < 0 || proto.OneofIndex >= parent.Proto.OneofDecl.Count) |
||||
{ |
||||
throw new DescriptorValidationException(this, |
||||
"FieldDescriptorProto.oneof_index is out of range for type " + parent.Name); |
||||
} |
||||
containingOneof = parent.Oneofs[proto.OneofIndex]; |
||||
} |
||||
|
||||
file.DescriptorPool.AddSymbol(this); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// The brief name of the descriptor's target. |
||||
/// </summary> |
||||
public override string Name { get { return proto.Name; } } |
||||
|
||||
internal FieldDescriptorProto Proto { get { return proto; } } |
||||
|
||||
/// <summary> |
||||
/// Maps a field type as included in the .proto file to a FieldType. |
||||
/// </summary> |
||||
private static FieldType GetFieldTypeFromProtoType(FieldDescriptorProto.Types.Type type) |
||||
{ |
||||
switch (type) |
||||
{ |
||||
case FieldDescriptorProto.Types.Type.TYPE_DOUBLE: |
||||
return FieldType.Double; |
||||
case FieldDescriptorProto.Types.Type.TYPE_FLOAT: |
||||
return FieldType.Float; |
||||
case FieldDescriptorProto.Types.Type.TYPE_INT64: |
||||
return FieldType.Int64; |
||||
case FieldDescriptorProto.Types.Type.TYPE_UINT64: |
||||
return FieldType.UInt64; |
||||
case FieldDescriptorProto.Types.Type.TYPE_INT32: |
||||
return FieldType.Int32; |
||||
case FieldDescriptorProto.Types.Type.TYPE_FIXED64: |
||||
return FieldType.Fixed64; |
||||
case FieldDescriptorProto.Types.Type.TYPE_FIXED32: |
||||
return FieldType.Fixed32; |
||||
case FieldDescriptorProto.Types.Type.TYPE_BOOL: |
||||
return FieldType.Bool; |
||||
case FieldDescriptorProto.Types.Type.TYPE_STRING: |
||||
return FieldType.String; |
||||
case FieldDescriptorProto.Types.Type.TYPE_GROUP: |
||||
return FieldType.Group; |
||||
case FieldDescriptorProto.Types.Type.TYPE_MESSAGE: |
||||
return FieldType.Message; |
||||
case FieldDescriptorProto.Types.Type.TYPE_BYTES: |
||||
return FieldType.Bytes; |
||||
case FieldDescriptorProto.Types.Type.TYPE_UINT32: |
||||
return FieldType.UInt32; |
||||
case FieldDescriptorProto.Types.Type.TYPE_ENUM: |
||||
return FieldType.Enum; |
||||
case FieldDescriptorProto.Types.Type.TYPE_SFIXED32: |
||||
return FieldType.SFixed32; |
||||
case FieldDescriptorProto.Types.Type.TYPE_SFIXED64: |
||||
return FieldType.SFixed64; |
||||
case FieldDescriptorProto.Types.Type.TYPE_SINT32: |
||||
return FieldType.SInt32; |
||||
case FieldDescriptorProto.Types.Type.TYPE_SINT64: |
||||
return FieldType.SInt64; |
||||
default: |
||||
throw new ArgumentException("Invalid type specified"); |
||||
} |
||||
} |
||||
|
||||
public bool IsRepeated |
||||
{ |
||||
get { return Proto.Label == FieldDescriptorProto.Types.Label.LABEL_REPEATED; } |
||||
} |
||||
|
||||
public bool IsMap |
||||
{ |
||||
get { return fieldType == FieldType.Message && messageType.Proto.Options != null && messageType.Proto.Options.MapEntry; } |
||||
} |
||||
|
||||
public bool IsPacked |
||||
{ |
||||
get { return Proto.Options != null && Proto.Options.Packed; } |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Get the field's containing type. For extensions, this is the type being |
||||
/// extended, not the location where the extension was defined. See |
||||
/// <see cref="ExtensionScope" />. |
||||
/// </summary> |
||||
public MessageDescriptor ContainingType |
||||
{ |
||||
get { return containingType; } |
||||
} |
||||
|
||||
public OneofDescriptor ContainingOneof |
||||
{ |
||||
get { return containingOneof; } |
||||
} |
||||
|
||||
public FieldType FieldType |
||||
{ |
||||
get { return fieldType; } |
||||
} |
||||
|
||||
public int FieldNumber |
||||
{ |
||||
get { return Proto.Number; } |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Compares this descriptor with another one, ordering in "canonical" order |
||||
/// which simply means ascending order by field number. <paramref name="other"/> |
||||
/// must be a field of the same type, i.e. the <see cref="ContainingType"/> of |
||||
/// both fields must be the same. |
||||
/// </summary> |
||||
public int CompareTo(FieldDescriptor other) |
||||
{ |
||||
if (other.containingType != containingType) |
||||
{ |
||||
throw new ArgumentException("FieldDescriptors can only be compared to other FieldDescriptors " + |
||||
"for fields of the same message type."); |
||||
} |
||||
return FieldNumber - other.FieldNumber; |
||||
} |
||||
|
||||
/// <summary> |
||||
/// For enum fields, returns the field's type. |
||||
/// </summary> |
||||
public EnumDescriptor EnumType |
||||
{ |
||||
get |
||||
{ |
||||
if (fieldType != FieldType.Enum) |
||||
{ |
||||
throw new InvalidOperationException("EnumType is only valid for enum fields."); |
||||
} |
||||
return enumType; |
||||
} |
||||
} |
||||
|
||||
/// <summary> |
||||
/// For embedded message and group fields, returns the field's type. |
||||
/// </summary> |
||||
public MessageDescriptor MessageType |
||||
{ |
||||
get |
||||
{ |
||||
if (fieldType != FieldType.Message) |
||||
{ |
||||
throw new InvalidOperationException("MessageType is only valid for enum fields."); |
||||
} |
||||
return messageType; |
||||
} |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Look up and cross-link all field types etc. |
||||
/// </summary> |
||||
internal void CrossLink() |
||||
{ |
||||
if (Proto.TypeName != "") |
||||
{ |
||||
IDescriptor typeDescriptor = |
||||
File.DescriptorPool.LookupSymbol(Proto.TypeName, this); |
||||
|
||||
if (Proto.Type != 0) |
||||
{ |
||||
// Choose field type based on symbol. |
||||
if (typeDescriptor is MessageDescriptor) |
||||
{ |
||||
fieldType = FieldType.Message; |
||||
} |
||||
else if (typeDescriptor is EnumDescriptor) |
||||
{ |
||||
fieldType = FieldType.Enum; |
||||
} |
||||
else |
||||
{ |
||||
throw new DescriptorValidationException(this, "\"" + Proto.TypeName + "\" is not a type."); |
||||
} |
||||
} |
||||
|
||||
if (fieldType == FieldType.Message) |
||||
{ |
||||
if (!(typeDescriptor is MessageDescriptor)) |
||||
{ |
||||
throw new DescriptorValidationException(this, |
||||
"\"" + Proto.TypeName + "\" is not a message type."); |
||||
} |
||||
messageType = (MessageDescriptor) typeDescriptor; |
||||
|
||||
if (Proto.DefaultValue != "") |
||||
{ |
||||
throw new DescriptorValidationException(this, "Messages can't have default values."); |
||||
} |
||||
} |
||||
else if (fieldType == FieldType.Enum) |
||||
{ |
||||
if (!(typeDescriptor is EnumDescriptor)) |
||||
{ |
||||
throw new DescriptorValidationException(this, "\"" + Proto.TypeName + "\" is not an enum type."); |
||||
} |
||||
enumType = (EnumDescriptor) typeDescriptor; |
||||
} |
||||
else |
||||
{ |
||||
throw new DescriptorValidationException(this, "Field with primitive type has type_name."); |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
if (fieldType == FieldType.Message || fieldType == FieldType.Enum) |
||||
{ |
||||
throw new DescriptorValidationException(this, "Field with message or enum type missing type_name."); |
||||
} |
||||
} |
||||
|
||||
// Note: no attempt to perform any default value parsing |
||||
|
||||
File.DescriptorPool.AddFieldByNumber(this); |
||||
|
||||
if (containingType != null && containingType.Proto.Options != null && containingType.Proto.Options.MessageSetWireFormat) |
||||
{ |
||||
throw new DescriptorValidationException(this, "MessageSet format is not supported."); |
||||
} |
||||
} |
||||
} |
||||
#region Copyright notice and license |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2008 Google Inc. All rights reserved. |
||||
// https://developers.google.com/protocol-buffers/ |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
#endregion |
||||
|
||||
using System; |
||||
|
||||
namespace Google.Protobuf.Reflection |
||||
{ |
||||
/// <summary> |
||||
/// Descriptor for a field or extension within a message in a .proto file. |
||||
/// </summary> |
||||
public sealed class FieldDescriptor : DescriptorBase, IComparable<FieldDescriptor> |
||||
{ |
||||
private readonly FieldDescriptorProto proto; |
||||
private EnumDescriptor enumType; |
||||
private MessageDescriptor messageType; |
||||
private readonly MessageDescriptor containingType; |
||||
private readonly OneofDescriptor containingOneof; |
||||
private FieldType fieldType; |
||||
|
||||
internal FieldDescriptor(FieldDescriptorProto proto, FileDescriptor file, |
||||
MessageDescriptor parent, int index) |
||||
: base(file, file.ComputeFullName(parent, proto.Name), index) |
||||
{ |
||||
this.proto = proto; |
||||
if (proto.Type != 0) |
||||
{ |
||||
fieldType = GetFieldTypeFromProtoType(proto.Type); |
||||
} |
||||
|
||||
if (FieldNumber <= 0) |
||||
{ |
||||
throw new DescriptorValidationException(this, |
||||
"Field numbers must be positive integers."); |
||||
} |
||||
containingType = parent; |
||||
// OneofIndex "defaults" to -1 due to a hack in FieldDescriptor.OnConstruction. |
||||
if (proto.OneofIndex != -1) |
||||
{ |
||||
if (proto.OneofIndex < 0 || proto.OneofIndex >= parent.Proto.OneofDecl.Count) |
||||
{ |
||||
throw new DescriptorValidationException(this, |
||||
"FieldDescriptorProto.oneof_index is out of range for type " + parent.Name); |
||||
} |
||||
containingOneof = parent.Oneofs[proto.OneofIndex]; |
||||
} |
||||
|
||||
file.DescriptorPool.AddSymbol(this); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// The brief name of the descriptor's target. |
||||
/// </summary> |
||||
public override string Name { get { return proto.Name; } } |
||||
|
||||
internal FieldDescriptorProto Proto { get { return proto; } } |
||||
|
||||
/// <summary> |
||||
/// Maps a field type as included in the .proto file to a FieldType. |
||||
/// </summary> |
||||
private static FieldType GetFieldTypeFromProtoType(FieldDescriptorProto.Types.Type type) |
||||
{ |
||||
switch (type) |
||||
{ |
||||
case FieldDescriptorProto.Types.Type.TYPE_DOUBLE: |
||||
return FieldType.Double; |
||||
case FieldDescriptorProto.Types.Type.TYPE_FLOAT: |
||||
return FieldType.Float; |
||||
case FieldDescriptorProto.Types.Type.TYPE_INT64: |
||||
return FieldType.Int64; |
||||
case FieldDescriptorProto.Types.Type.TYPE_UINT64: |
||||
return FieldType.UInt64; |
||||
case FieldDescriptorProto.Types.Type.TYPE_INT32: |
||||
return FieldType.Int32; |
||||
case FieldDescriptorProto.Types.Type.TYPE_FIXED64: |
||||
return FieldType.Fixed64; |
||||
case FieldDescriptorProto.Types.Type.TYPE_FIXED32: |
||||
return FieldType.Fixed32; |
||||
case FieldDescriptorProto.Types.Type.TYPE_BOOL: |
||||
return FieldType.Bool; |
||||
case FieldDescriptorProto.Types.Type.TYPE_STRING: |
||||
return FieldType.String; |
||||
case FieldDescriptorProto.Types.Type.TYPE_GROUP: |
||||
return FieldType.Group; |
||||
case FieldDescriptorProto.Types.Type.TYPE_MESSAGE: |
||||
return FieldType.Message; |
||||
case FieldDescriptorProto.Types.Type.TYPE_BYTES: |
||||
return FieldType.Bytes; |
||||
case FieldDescriptorProto.Types.Type.TYPE_UINT32: |
||||
return FieldType.UInt32; |
||||
case FieldDescriptorProto.Types.Type.TYPE_ENUM: |
||||
return FieldType.Enum; |
||||
case FieldDescriptorProto.Types.Type.TYPE_SFIXED32: |
||||
return FieldType.SFixed32; |
||||
case FieldDescriptorProto.Types.Type.TYPE_SFIXED64: |
||||
return FieldType.SFixed64; |
||||
case FieldDescriptorProto.Types.Type.TYPE_SINT32: |
||||
return FieldType.SInt32; |
||||
case FieldDescriptorProto.Types.Type.TYPE_SINT64: |
||||
return FieldType.SInt64; |
||||
default: |
||||
throw new ArgumentException("Invalid type specified"); |
||||
} |
||||
} |
||||
|
||||
public bool IsRepeated |
||||
{ |
||||
get { return Proto.Label == FieldDescriptorProto.Types.Label.LABEL_REPEATED; } |
||||
} |
||||
|
||||
public bool IsMap |
||||
{ |
||||
get { return fieldType == FieldType.Message && messageType.Proto.Options != null && messageType.Proto.Options.MapEntry; } |
||||
} |
||||
|
||||
public bool IsPacked |
||||
{ |
||||
get { return Proto.Options != null && Proto.Options.Packed; } |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Get the field's containing type. For extensions, this is the type being |
||||
/// extended, not the location where the extension was defined. See |
||||
/// <see cref="ExtensionScope" />. |
||||
/// </summary> |
||||
public MessageDescriptor ContainingType |
||||
{ |
||||
get { return containingType; } |
||||
} |
||||
|
||||
public OneofDescriptor ContainingOneof |
||||
{ |
||||
get { return containingOneof; } |
||||
} |
||||
|
||||
public FieldType FieldType |
||||
{ |
||||
get { return fieldType; } |
||||
} |
||||
|
||||
public int FieldNumber |
||||
{ |
||||
get { return Proto.Number; } |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Compares this descriptor with another one, ordering in "canonical" order |
||||
/// which simply means ascending order by field number. <paramref name="other"/> |
||||
/// must be a field of the same type, i.e. the <see cref="ContainingType"/> of |
||||
/// both fields must be the same. |
||||
/// </summary> |
||||
public int CompareTo(FieldDescriptor other) |
||||
{ |
||||
if (other.containingType != containingType) |
||||
{ |
||||
throw new ArgumentException("FieldDescriptors can only be compared to other FieldDescriptors " + |
||||
"for fields of the same message type."); |
||||
} |
||||
return FieldNumber - other.FieldNumber; |
||||
} |
||||
|
||||
/// <summary> |
||||
/// For enum fields, returns the field's type. |
||||
/// </summary> |
||||
public EnumDescriptor EnumType |
||||
{ |
||||
get |
||||
{ |
||||
if (fieldType != FieldType.Enum) |
||||
{ |
||||
throw new InvalidOperationException("EnumType is only valid for enum fields."); |
||||
} |
||||
return enumType; |
||||
} |
||||
} |
||||
|
||||
/// <summary> |
||||
/// For embedded message and group fields, returns the field's type. |
||||
/// </summary> |
||||
public MessageDescriptor MessageType |
||||
{ |
||||
get |
||||
{ |
||||
if (fieldType != FieldType.Message) |
||||
{ |
||||
throw new InvalidOperationException("MessageType is only valid for enum fields."); |
||||
} |
||||
return messageType; |
||||
} |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Look up and cross-link all field types etc. |
||||
/// </summary> |
||||
internal void CrossLink() |
||||
{ |
||||
if (Proto.TypeName != "") |
||||
{ |
||||
IDescriptor typeDescriptor = |
||||
File.DescriptorPool.LookupSymbol(Proto.TypeName, this); |
||||
|
||||
if (Proto.Type != 0) |
||||
{ |
||||
// Choose field type based on symbol. |
||||
if (typeDescriptor is MessageDescriptor) |
||||
{ |
||||
fieldType = FieldType.Message; |
||||
} |
||||
else if (typeDescriptor is EnumDescriptor) |
||||
{ |
||||
fieldType = FieldType.Enum; |
||||
} |
||||
else |
||||
{ |
||||
throw new DescriptorValidationException(this, "\"" + Proto.TypeName + "\" is not a type."); |
||||
} |
||||
} |
||||
|
||||
if (fieldType == FieldType.Message) |
||||
{ |
||||
if (!(typeDescriptor is MessageDescriptor)) |
||||
{ |
||||
throw new DescriptorValidationException(this, |
||||
"\"" + Proto.TypeName + "\" is not a message type."); |
||||
} |
||||
messageType = (MessageDescriptor) typeDescriptor; |
||||
|
||||
if (Proto.DefaultValue != "") |
||||
{ |
||||
throw new DescriptorValidationException(this, "Messages can't have default values."); |
||||
} |
||||
} |
||||
else if (fieldType == FieldType.Enum) |
||||
{ |
||||
if (!(typeDescriptor is EnumDescriptor)) |
||||
{ |
||||
throw new DescriptorValidationException(this, "\"" + Proto.TypeName + "\" is not an enum type."); |
||||
} |
||||
enumType = (EnumDescriptor) typeDescriptor; |
||||
} |
||||
else |
||||
{ |
||||
throw new DescriptorValidationException(this, "Field with primitive type has type_name."); |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
if (fieldType == FieldType.Message || fieldType == FieldType.Enum) |
||||
{ |
||||
throw new DescriptorValidationException(this, "Field with message or enum type missing type_name."); |
||||
} |
||||
} |
||||
|
||||
// Note: no attempt to perform any default value parsing |
||||
|
||||
File.DescriptorPool.AddFieldByNumber(this); |
||||
|
||||
if (containingType != null && containingType.Proto.Options != null && containingType.Proto.Options.MessageSetWireFormat) |
||||
{ |
||||
throw new DescriptorValidationException(this, "MessageSet format is not supported."); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -1,60 +1,60 @@ |
||||
#region Copyright notice and license |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2008 Google Inc. All rights reserved. |
||||
// https://developers.google.com/protocol-buffers/ |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
#endregion |
||||
|
||||
namespace Google.Protobuf.Descriptors |
||||
{ |
||||
/// <summary> |
||||
/// Enumeration of all the possible field types. The odd formatting is to make it very clear |
||||
/// which attribute applies to which value, while maintaining a compact format. |
||||
/// </summary> |
||||
public enum FieldType |
||||
{ |
||||
Double, |
||||
Float, |
||||
Int64, |
||||
UInt64, |
||||
Int32, |
||||
Fixed64, |
||||
Fixed32, |
||||
Bool, |
||||
String, |
||||
Group, |
||||
Message, |
||||
Bytes, |
||||
UInt32, |
||||
SFixed32, |
||||
SFixed64, |
||||
SInt32, |
||||
SInt64, |
||||
Enum |
||||
} |
||||
#region Copyright notice and license |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2008 Google Inc. All rights reserved. |
||||
// https://developers.google.com/protocol-buffers/ |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
#endregion |
||||
|
||||
namespace Google.Protobuf.Reflection |
||||
{ |
||||
/// <summary> |
||||
/// Enumeration of all the possible field types. The odd formatting is to make it very clear |
||||
/// which attribute applies to which value, while maintaining a compact format. |
||||
/// </summary> |
||||
public enum FieldType |
||||
{ |
||||
Double, |
||||
Float, |
||||
Int64, |
||||
UInt64, |
||||
Int32, |
||||
Fixed64, |
||||
Fixed32, |
||||
Bool, |
||||
String, |
||||
Group, |
||||
Message, |
||||
Bytes, |
||||
UInt32, |
||||
SFixed32, |
||||
SFixed64, |
||||
SInt32, |
||||
SInt64, |
||||
Enum |
||||
} |
||||
} |
@ -1,354 +1,352 @@ |
||||
#region Copyright notice and license |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2008 Google Inc. All rights reserved. |
||||
// https://developers.google.com/protocol-buffers/ |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
#endregion |
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Collections.ObjectModel; |
||||
using Google.Protobuf.DescriptorProtos; |
||||
using FileOptions = Google.Protobuf.DescriptorProtos.FileOptions; |
||||
|
||||
namespace Google.Protobuf.Descriptors |
||||
{ |
||||
/// <summary> |
||||
/// Describes a .proto file, including everything defined within. |
||||
/// IDescriptor is implemented such that the File property returns this descriptor, |
||||
/// and the FullName is the same as the Name. |
||||
/// </summary> |
||||
public sealed class FileDescriptor : IDescriptor |
||||
{ |
||||
private readonly FileDescriptorProto proto; |
||||
private readonly IList<MessageDescriptor> messageTypes; |
||||
private readonly IList<EnumDescriptor> enumTypes; |
||||
private readonly IList<ServiceDescriptor> services; |
||||
private readonly IList<FileDescriptor> dependencies; |
||||
private readonly IList<FileDescriptor> publicDependencies; |
||||
private readonly DescriptorPool pool; |
||||
|
||||
public enum ProtoSyntax |
||||
{ |
||||
Proto2, |
||||
Proto3 |
||||
} |
||||
|
||||
public ProtoSyntax Syntax |
||||
{ |
||||
get { return proto.Syntax == "proto3" ? ProtoSyntax.Proto3 : ProtoSyntax.Proto2; } |
||||
} |
||||
|
||||
private FileDescriptor(FileDescriptorProto proto, FileDescriptor[] dependencies, DescriptorPool pool, bool allowUnknownDependencies) |
||||
{ |
||||
this.pool = pool; |
||||
this.proto = proto; |
||||
this.dependencies = new ReadOnlyCollection<FileDescriptor>((FileDescriptor[]) dependencies.Clone()); |
||||
|
||||
publicDependencies = DeterminePublicDependencies(this, proto, dependencies, allowUnknownDependencies); |
||||
|
||||
pool.AddPackage(Package, this); |
||||
|
||||
messageTypes = DescriptorUtil.ConvertAndMakeReadOnly(proto.MessageType, |
||||
(message, index) => |
||||
new MessageDescriptor(message, this, null, index)); |
||||
|
||||
enumTypes = DescriptorUtil.ConvertAndMakeReadOnly(proto.EnumType, |
||||
(enumType, index) => |
||||
new EnumDescriptor(enumType, this, null, index)); |
||||
|
||||
services = DescriptorUtil.ConvertAndMakeReadOnly(proto.Service, |
||||
(service, index) => |
||||
new ServiceDescriptor(service, this, index)); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Computes the full name of a descriptor within this file, with an optional parent message. |
||||
/// </summary> |
||||
internal string ComputeFullName(MessageDescriptor parent, string name) |
||||
{ |
||||
if (parent != null) |
||||
{ |
||||
return parent.FullName + "." + name; |
||||
} |
||||
if (Package.Length > 0) |
||||
{ |
||||
return Package + "." + name; |
||||
} |
||||
return name; |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Extracts public dependencies from direct dependencies. This is a static method despite its |
||||
/// first parameter, as the value we're in the middle of constructing is only used for exceptions. |
||||
/// </summary> |
||||
private static IList<FileDescriptor> DeterminePublicDependencies(FileDescriptor @this, FileDescriptorProto proto, FileDescriptor[] dependencies, bool allowUnknownDependencies) |
||||
{ |
||||
var nameToFileMap = new Dictionary<string, FileDescriptor>(); |
||||
foreach (var file in dependencies) |
||||
{ |
||||
nameToFileMap[file.Name] = file; |
||||
} |
||||
var publicDependencies = new List<FileDescriptor>(); |
||||
for (int i = 0; i < proto.PublicDependency.Count; i++) |
||||
{ |
||||
int index = proto.PublicDependency[i]; |
||||
if (index < 0 || index >= proto.Dependency.Count) |
||||
{ |
||||
throw new DescriptorValidationException(@this, "Invalid public dependency index."); |
||||
} |
||||
string name = proto.Dependency[index]; |
||||
FileDescriptor file = nameToFileMap[name]; |
||||
if (file == null) |
||||
{ |
||||
if (!allowUnknownDependencies) |
||||
{ |
||||
throw new DescriptorValidationException(@this, "Invalid public dependency: " + name); |
||||
} |
||||
// Ignore unknown dependencies. |
||||
} |
||||
else |
||||
{ |
||||
publicDependencies.Add(file); |
||||
} |
||||
} |
||||
return new ReadOnlyCollection<FileDescriptor>(publicDependencies); |
||||
} |
||||
|
||||
/// <value> |
||||
/// The descriptor in its protocol message representation. |
||||
/// </value> |
||||
internal FileDescriptorProto Proto |
||||
{ |
||||
get { return proto; } |
||||
} |
||||
|
||||
/// <value> |
||||
/// The file name. |
||||
/// </value> |
||||
public string Name |
||||
{ |
||||
get { return proto.Name; } |
||||
} |
||||
|
||||
/// <summary> |
||||
/// The package as declared in the .proto file. This may or may not |
||||
/// be equivalent to the .NET namespace of the generated classes. |
||||
/// </summary> |
||||
public string Package |
||||
{ |
||||
get { return proto.Package; } |
||||
} |
||||
|
||||
/// <value> |
||||
/// Unmodifiable list of top-level message types declared in this file. |
||||
/// </value> |
||||
public IList<MessageDescriptor> MessageTypes |
||||
{ |
||||
get { return messageTypes; } |
||||
} |
||||
|
||||
/// <value> |
||||
/// Unmodifiable list of top-level enum types declared in this file. |
||||
/// </value> |
||||
public IList<EnumDescriptor> EnumTypes |
||||
{ |
||||
get { return enumTypes; } |
||||
} |
||||
|
||||
/// <value> |
||||
/// Unmodifiable list of top-level services declared in this file. |
||||
/// </value> |
||||
public IList<ServiceDescriptor> Services |
||||
{ |
||||
get { return services; } |
||||
} |
||||
|
||||
/// <value> |
||||
/// Unmodifiable list of this file's dependencies (imports). |
||||
/// </value> |
||||
public IList<FileDescriptor> Dependencies |
||||
{ |
||||
get { return dependencies; } |
||||
} |
||||
|
||||
/// <value> |
||||
/// Unmodifiable list of this file's public dependencies (public imports). |
||||
/// </value> |
||||
public IList<FileDescriptor> PublicDependencies |
||||
{ |
||||
get { return publicDependencies; } |
||||
} |
||||
|
||||
/// <value> |
||||
/// Implementation of IDescriptor.FullName - just returns the same as Name. |
||||
/// </value> |
||||
string IDescriptor.FullName |
||||
{ |
||||
get { return Name; } |
||||
} |
||||
|
||||
/// <value> |
||||
/// Implementation of IDescriptor.File - just returns this descriptor. |
||||
/// </value> |
||||
FileDescriptor IDescriptor.File |
||||
{ |
||||
get { return this; } |
||||
} |
||||
|
||||
/// <value> |
||||
/// Pool containing symbol descriptors. |
||||
/// </value> |
||||
internal DescriptorPool DescriptorPool |
||||
{ |
||||
get { return pool; } |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Finds a type (message, enum, service or extension) in the file by name. Does not find nested types. |
||||
/// </summary> |
||||
/// <param name="name">The unqualified type name to look for.</param> |
||||
/// <typeparam name="T">The type of descriptor to look for (or ITypeDescriptor for any)</typeparam> |
||||
/// <returns>The type's descriptor, or null if not found.</returns> |
||||
public T FindTypeByName<T>(String name) |
||||
where T : class, IDescriptor |
||||
{ |
||||
// Don't allow looking up nested types. This will make optimization |
||||
// easier later. |
||||
if (name.IndexOf('.') != -1) |
||||
{ |
||||
return null; |
||||
} |
||||
if (Package.Length > 0) |
||||
{ |
||||
name = Package + "." + name; |
||||
} |
||||
T result = pool.FindSymbol<T>(name); |
||||
if (result != null && result.File == this) |
||||
{ |
||||
return result; |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Builds a FileDescriptor from its protocol buffer representation. |
||||
/// </summary> |
||||
/// <param name="proto">The protocol message form of the FileDescriptor.</param> |
||||
/// <param name="dependencies">FileDescriptors corresponding to all of the |
||||
/// file's dependencies, in the exact order listed in the .proto file. May be null, |
||||
/// in which case it is treated as an empty array.</param> |
||||
/// <param name="allowUnknownDependencies">Whether unknown dependencies are ignored (true) or cause an exception to be thrown (false).</param> |
||||
/// <exception cref="DescriptorValidationException">If <paramref name="proto"/> is not |
||||
/// a valid descriptor. This can occur for a number of reasons, such as a field |
||||
/// having an undefined type or because two messages were defined with the same name.</exception> |
||||
private static FileDescriptor BuildFrom(FileDescriptorProto proto, FileDescriptor[] dependencies, bool allowUnknownDependencies) |
||||
{ |
||||
// Building descriptors involves two steps: translating and linking. |
||||
// In the translation step (implemented by FileDescriptor's |
||||
// constructor), we build an object tree mirroring the |
||||
// FileDescriptorProto's tree and put all of the descriptors into the |
||||
// DescriptorPool's lookup tables. In the linking step, we look up all |
||||
// type references in the DescriptorPool, so that, for example, a |
||||
// FieldDescriptor for an embedded message contains a pointer directly |
||||
// to the Descriptor for that message's type. We also detect undefined |
||||
// types in the linking step. |
||||
if (dependencies == null) |
||||
{ |
||||
dependencies = new FileDescriptor[0]; |
||||
} |
||||
|
||||
DescriptorPool pool = new DescriptorPool(dependencies); |
||||
FileDescriptor result = new FileDescriptor(proto, dependencies, pool, allowUnknownDependencies); |
||||
|
||||
// TODO(jonskeet): Reinstate these checks, or get rid of them entirely. They aren't in the Java code, |
||||
// and fail for the CustomOptions test right now. (We get "descriptor.proto" vs "google/protobuf/descriptor.proto".) |
||||
//if (dependencies.Length != proto.DependencyCount) |
||||
//{ |
||||
// throw new DescriptorValidationException(result, |
||||
// "Dependencies passed to FileDescriptor.BuildFrom() don't match " + |
||||
// "those listed in the FileDescriptorProto."); |
||||
//} |
||||
//for (int i = 0; i < proto.DependencyCount; i++) |
||||
//{ |
||||
// if (dependencies[i].Name != proto.DependencyList[i]) |
||||
// { |
||||
// throw new DescriptorValidationException(result, |
||||
// "Dependencies passed to FileDescriptor.BuildFrom() don't match " + |
||||
// "those listed in the FileDescriptorProto."); |
||||
// } |
||||
//} |
||||
|
||||
result.CrossLink(); |
||||
return result; |
||||
} |
||||
|
||||
private void CrossLink() |
||||
{ |
||||
foreach (MessageDescriptor message in messageTypes) |
||||
{ |
||||
message.CrossLink(); |
||||
} |
||||
|
||||
foreach (ServiceDescriptor service in services) |
||||
{ |
||||
service.CrossLink(); |
||||
} |
||||
} |
||||
|
||||
public static FileDescriptor InternalBuildGeneratedFileFrom(byte[] descriptorData, |
||||
FileDescriptor[] dependencies) |
||||
{ |
||||
FileDescriptorProto proto; |
||||
try |
||||
{ |
||||
proto = FileDescriptorProto.Parser.ParseFrom(descriptorData); |
||||
} |
||||
catch (InvalidProtocolBufferException e) |
||||
{ |
||||
throw new ArgumentException("Failed to parse protocol buffer descriptor for generated code.", e); |
||||
} |
||||
|
||||
try |
||||
{ |
||||
// When building descriptors for generated code, we allow unknown |
||||
// dependencies by default. |
||||
return BuildFrom(proto, dependencies, true); |
||||
} |
||||
catch (DescriptorValidationException e) |
||||
{ |
||||
throw new ArgumentException("Invalid embedded descriptor for \"" + proto.Name + "\".", e); |
||||
} |
||||
} |
||||
|
||||
public override string ToString() |
||||
{ |
||||
return "FileDescriptor for " + proto.Name; |
||||
} |
||||
} |
||||
#region Copyright notice and license |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2008 Google Inc. All rights reserved. |
||||
// https://developers.google.com/protocol-buffers/ |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
#endregion |
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Collections.ObjectModel; |
||||
|
||||
namespace Google.Protobuf.Reflection |
||||
{ |
||||
/// <summary> |
||||
/// Describes a .proto file, including everything defined within. |
||||
/// IDescriptor is implemented such that the File property returns this descriptor, |
||||
/// and the FullName is the same as the Name. |
||||
/// </summary> |
||||
public sealed class FileDescriptor : IDescriptor |
||||
{ |
||||
private readonly FileDescriptorProto proto; |
||||
private readonly IList<MessageDescriptor> messageTypes; |
||||
private readonly IList<EnumDescriptor> enumTypes; |
||||
private readonly IList<ServiceDescriptor> services; |
||||
private readonly IList<FileDescriptor> dependencies; |
||||
private readonly IList<FileDescriptor> publicDependencies; |
||||
private readonly DescriptorPool pool; |
||||
|
||||
public enum ProtoSyntax |
||||
{ |
||||
Proto2, |
||||
Proto3 |
||||
} |
||||
|
||||
public ProtoSyntax Syntax |
||||
{ |
||||
get { return proto.Syntax == "proto3" ? ProtoSyntax.Proto3 : ProtoSyntax.Proto2; } |
||||
} |
||||
|
||||
private FileDescriptor(FileDescriptorProto proto, FileDescriptor[] dependencies, DescriptorPool pool, bool allowUnknownDependencies) |
||||
{ |
||||
this.pool = pool; |
||||
this.proto = proto; |
||||
this.dependencies = new ReadOnlyCollection<FileDescriptor>((FileDescriptor[]) dependencies.Clone()); |
||||
|
||||
publicDependencies = DeterminePublicDependencies(this, proto, dependencies, allowUnknownDependencies); |
||||
|
||||
pool.AddPackage(Package, this); |
||||
|
||||
messageTypes = DescriptorUtil.ConvertAndMakeReadOnly(proto.MessageType, |
||||
(message, index) => |
||||
new MessageDescriptor(message, this, null, index)); |
||||
|
||||
enumTypes = DescriptorUtil.ConvertAndMakeReadOnly(proto.EnumType, |
||||
(enumType, index) => |
||||
new EnumDescriptor(enumType, this, null, index)); |
||||
|
||||
services = DescriptorUtil.ConvertAndMakeReadOnly(proto.Service, |
||||
(service, index) => |
||||
new ServiceDescriptor(service, this, index)); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Computes the full name of a descriptor within this file, with an optional parent message. |
||||
/// </summary> |
||||
internal string ComputeFullName(MessageDescriptor parent, string name) |
||||
{ |
||||
if (parent != null) |
||||
{ |
||||
return parent.FullName + "." + name; |
||||
} |
||||
if (Package.Length > 0) |
||||
{ |
||||
return Package + "." + name; |
||||
} |
||||
return name; |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Extracts public dependencies from direct dependencies. This is a static method despite its |
||||
/// first parameter, as the value we're in the middle of constructing is only used for exceptions. |
||||
/// </summary> |
||||
private static IList<FileDescriptor> DeterminePublicDependencies(FileDescriptor @this, FileDescriptorProto proto, FileDescriptor[] dependencies, bool allowUnknownDependencies) |
||||
{ |
||||
var nameToFileMap = new Dictionary<string, FileDescriptor>(); |
||||
foreach (var file in dependencies) |
||||
{ |
||||
nameToFileMap[file.Name] = file; |
||||
} |
||||
var publicDependencies = new List<FileDescriptor>(); |
||||
for (int i = 0; i < proto.PublicDependency.Count; i++) |
||||
{ |
||||
int index = proto.PublicDependency[i]; |
||||
if (index < 0 || index >= proto.Dependency.Count) |
||||
{ |
||||
throw new DescriptorValidationException(@this, "Invalid public dependency index."); |
||||
} |
||||
string name = proto.Dependency[index]; |
||||
FileDescriptor file = nameToFileMap[name]; |
||||
if (file == null) |
||||
{ |
||||
if (!allowUnknownDependencies) |
||||
{ |
||||
throw new DescriptorValidationException(@this, "Invalid public dependency: " + name); |
||||
} |
||||
// Ignore unknown dependencies. |
||||
} |
||||
else |
||||
{ |
||||
publicDependencies.Add(file); |
||||
} |
||||
} |
||||
return new ReadOnlyCollection<FileDescriptor>(publicDependencies); |
||||
} |
||||
|
||||
/// <value> |
||||
/// The descriptor in its protocol message representation. |
||||
/// </value> |
||||
internal FileDescriptorProto Proto |
||||
{ |
||||
get { return proto; } |
||||
} |
||||
|
||||
/// <value> |
||||
/// The file name. |
||||
/// </value> |
||||
public string Name |
||||
{ |
||||
get { return proto.Name; } |
||||
} |
||||
|
||||
/// <summary> |
||||
/// The package as declared in the .proto file. This may or may not |
||||
/// be equivalent to the .NET namespace of the generated classes. |
||||
/// </summary> |
||||
public string Package |
||||
{ |
||||
get { return proto.Package; } |
||||
} |
||||
|
||||
/// <value> |
||||
/// Unmodifiable list of top-level message types declared in this file. |
||||
/// </value> |
||||
public IList<MessageDescriptor> MessageTypes |
||||
{ |
||||
get { return messageTypes; } |
||||
} |
||||
|
||||
/// <value> |
||||
/// Unmodifiable list of top-level enum types declared in this file. |
||||
/// </value> |
||||
public IList<EnumDescriptor> EnumTypes |
||||
{ |
||||
get { return enumTypes; } |
||||
} |
||||
|
||||
/// <value> |
||||
/// Unmodifiable list of top-level services declared in this file. |
||||
/// </value> |
||||
public IList<ServiceDescriptor> Services |
||||
{ |
||||
get { return services; } |
||||
} |
||||
|
||||
/// <value> |
||||
/// Unmodifiable list of this file's dependencies (imports). |
||||
/// </value> |
||||
public IList<FileDescriptor> Dependencies |
||||
{ |
||||
get { return dependencies; } |
||||
} |
||||
|
||||
/// <value> |
||||
/// Unmodifiable list of this file's public dependencies (public imports). |
||||
/// </value> |
||||
public IList<FileDescriptor> PublicDependencies |
||||
{ |
||||
get { return publicDependencies; } |
||||
} |
||||
|
||||
/// <value> |
||||
/// Implementation of IDescriptor.FullName - just returns the same as Name. |
||||
/// </value> |
||||
string IDescriptor.FullName |
||||
{ |
||||
get { return Name; } |
||||
} |
||||
|
||||
/// <value> |
||||
/// Implementation of IDescriptor.File - just returns this descriptor. |
||||
/// </value> |
||||
FileDescriptor IDescriptor.File |
||||
{ |
||||
get { return this; } |
||||
} |
||||
|
||||
/// <value> |
||||
/// Pool containing symbol descriptors. |
||||
/// </value> |
||||
internal DescriptorPool DescriptorPool |
||||
{ |
||||
get { return pool; } |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Finds a type (message, enum, service or extension) in the file by name. Does not find nested types. |
||||
/// </summary> |
||||
/// <param name="name">The unqualified type name to look for.</param> |
||||
/// <typeparam name="T">The type of descriptor to look for (or ITypeDescriptor for any)</typeparam> |
||||
/// <returns>The type's descriptor, or null if not found.</returns> |
||||
public T FindTypeByName<T>(String name) |
||||
where T : class, IDescriptor |
||||
{ |
||||
// Don't allow looking up nested types. This will make optimization |
||||
// easier later. |
||||
if (name.IndexOf('.') != -1) |
||||
{ |
||||
return null; |
||||
} |
||||
if (Package.Length > 0) |
||||
{ |
||||
name = Package + "." + name; |
||||
} |
||||
T result = pool.FindSymbol<T>(name); |
||||
if (result != null && result.File == this) |
||||
{ |
||||
return result; |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Builds a FileDescriptor from its protocol buffer representation. |
||||
/// </summary> |
||||
/// <param name="proto">The protocol message form of the FileDescriptor.</param> |
||||
/// <param name="dependencies">FileDescriptors corresponding to all of the |
||||
/// file's dependencies, in the exact order listed in the .proto file. May be null, |
||||
/// in which case it is treated as an empty array.</param> |
||||
/// <param name="allowUnknownDependencies">Whether unknown dependencies are ignored (true) or cause an exception to be thrown (false).</param> |
||||
/// <exception cref="DescriptorValidationException">If <paramref name="proto"/> is not |
||||
/// a valid descriptor. This can occur for a number of reasons, such as a field |
||||
/// having an undefined type or because two messages were defined with the same name.</exception> |
||||
private static FileDescriptor BuildFrom(FileDescriptorProto proto, FileDescriptor[] dependencies, bool allowUnknownDependencies) |
||||
{ |
||||
// Building descriptors involves two steps: translating and linking. |
||||
// In the translation step (implemented by FileDescriptor's |
||||
// constructor), we build an object tree mirroring the |
||||
// FileDescriptorProto's tree and put all of the descriptors into the |
||||
// DescriptorPool's lookup tables. In the linking step, we look up all |
||||
// type references in the DescriptorPool, so that, for example, a |
||||
// FieldDescriptor for an embedded message contains a pointer directly |
||||
// to the Descriptor for that message's type. We also detect undefined |
||||
// types in the linking step. |
||||
if (dependencies == null) |
||||
{ |
||||
dependencies = new FileDescriptor[0]; |
||||
} |
||||
|
||||
DescriptorPool pool = new DescriptorPool(dependencies); |
||||
FileDescriptor result = new FileDescriptor(proto, dependencies, pool, allowUnknownDependencies); |
||||
|
||||
// TODO(jonskeet): Reinstate these checks, or get rid of them entirely. They aren't in the Java code, |
||||
// and fail for the CustomOptions test right now. (We get "descriptor.proto" vs "google/protobuf/descriptor.proto".) |
||||
//if (dependencies.Length != proto.DependencyCount) |
||||
//{ |
||||
// throw new DescriptorValidationException(result, |
||||
// "Dependencies passed to FileDescriptor.BuildFrom() don't match " + |
||||
// "those listed in the FileDescriptorProto."); |
||||
//} |
||||
//for (int i = 0; i < proto.DependencyCount; i++) |
||||
//{ |
||||
// if (dependencies[i].Name != proto.DependencyList[i]) |
||||
// { |
||||
// throw new DescriptorValidationException(result, |
||||
// "Dependencies passed to FileDescriptor.BuildFrom() don't match " + |
||||
// "those listed in the FileDescriptorProto."); |
||||
// } |
||||
//} |
||||
|
||||
result.CrossLink(); |
||||
return result; |
||||
} |
||||
|
||||
private void CrossLink() |
||||
{ |
||||
foreach (MessageDescriptor message in messageTypes) |
||||
{ |
||||
message.CrossLink(); |
||||
} |
||||
|
||||
foreach (ServiceDescriptor service in services) |
||||
{ |
||||
service.CrossLink(); |
||||
} |
||||
} |
||||
|
||||
public static FileDescriptor InternalBuildGeneratedFileFrom(byte[] descriptorData, |
||||
FileDescriptor[] dependencies) |
||||
{ |
||||
FileDescriptorProto proto; |
||||
try |
||||
{ |
||||
proto = FileDescriptorProto.Parser.ParseFrom(descriptorData); |
||||
} |
||||
catch (InvalidProtocolBufferException e) |
||||
{ |
||||
throw new ArgumentException("Failed to parse protocol buffer descriptor for generated code.", e); |
||||
} |
||||
|
||||
try |
||||
{ |
||||
// When building descriptors for generated code, we allow unknown |
||||
// dependencies by default. |
||||
return BuildFrom(proto, dependencies, true); |
||||
} |
||||
catch (DescriptorValidationException e) |
||||
{ |
||||
throw new ArgumentException("Invalid embedded descriptor for \"" + proto.Name + "\".", e); |
||||
} |
||||
} |
||||
|
||||
public override string ToString() |
||||
{ |
||||
return "FileDescriptor for " + proto.Name; |
||||
} |
||||
} |
||||
} |
@ -1,44 +1,44 @@ |
||||
#region Copyright notice and license |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2008 Google Inc. All rights reserved. |
||||
// https://developers.google.com/protocol-buffers/ |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
#endregion |
||||
|
||||
namespace Google.Protobuf.Descriptors |
||||
{ |
||||
/// <summary> |
||||
/// Interface implemented by all descriptor types. |
||||
/// </summary> |
||||
public interface IDescriptor |
||||
{ |
||||
string Name { get; } |
||||
string FullName { get; } |
||||
FileDescriptor File { get; } |
||||
} |
||||
#region Copyright notice and license |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2008 Google Inc. All rights reserved. |
||||
// https://developers.google.com/protocol-buffers/ |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
#endregion |
||||
|
||||
namespace Google.Protobuf.Reflection |
||||
{ |
||||
/// <summary> |
||||
/// Interface implemented by all descriptor types. |
||||
/// </summary> |
||||
public interface IDescriptor |
||||
{ |
||||
string Name { get; } |
||||
string FullName { get; } |
||||
FileDescriptor File { get; } |
||||
} |
||||
} |
@ -1,72 +1,70 @@ |
||||
#region Copyright notice and license |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2008 Google Inc. All rights reserved. |
||||
// https://developers.google.com/protocol-buffers/ |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
#endregion |
||||
|
||||
using Google.Protobuf.Descriptors; |
||||
|
||||
namespace Google.Protobuf.FieldAccess |
||||
{ |
||||
/// <summary> |
||||
/// Allows fields to be reflectively accessed. |
||||
/// </summary> |
||||
public interface IFieldAccessor |
||||
{ |
||||
/// <summary> |
||||
/// Returns the descriptor associated with this field. |
||||
/// </summary> |
||||
FieldDescriptor Descriptor { get; } |
||||
|
||||
// TODO: Should the argument type for these messages by IReflectedMessage? |
||||
|
||||
/// <summary> |
||||
/// Clears the field in the specified message. (For repeated fields, |
||||
/// this clears the list.) |
||||
/// </summary> |
||||
void Clear(object message); |
||||
|
||||
/// <summary> |
||||
/// Fetches the field value. For repeated values, this will be an |
||||
/// <see cref="IList"/> implementation. For map values, this will be an |
||||
/// <see cref="IDictionary"/> implementation. |
||||
/// </summary> |
||||
object GetValue(object message); |
||||
|
||||
/// <summary> |
||||
/// Mutator for single "simple" fields only. |
||||
/// </summary> |
||||
/// <remarks> |
||||
/// Repeated fields are mutated by fetching the value and manipulating it as a list. |
||||
/// Map fields are mutated by fetching the value and manipulating it as a dictionary. |
||||
/// </remarks> |
||||
/// <exception cref="InvalidOperationException">The field is not a "simple" field, or the message is frozen.</exception> |
||||
void SetValue(object message, object value); |
||||
} |
||||
#region Copyright notice and license |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2008 Google Inc. All rights reserved. |
||||
// https://developers.google.com/protocol-buffers/ |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
#endregion |
||||
|
||||
namespace Google.Protobuf.Reflection |
||||
{ |
||||
/// <summary> |
||||
/// Allows fields to be reflectively accessed. |
||||
/// </summary> |
||||
public interface IFieldAccessor |
||||
{ |
||||
/// <summary> |
||||
/// Returns the descriptor associated with this field. |
||||
/// </summary> |
||||
FieldDescriptor Descriptor { get; } |
||||
|
||||
// TODO: Should the argument type for these messages by IReflectedMessage? |
||||
|
||||
/// <summary> |
||||
/// Clears the field in the specified message. (For repeated fields, |
||||
/// this clears the list.) |
||||
/// </summary> |
||||
void Clear(object message); |
||||
|
||||
/// <summary> |
||||
/// Fetches the field value. For repeated values, this will be an |
||||
/// <see cref="IList"/> implementation. For map values, this will be an |
||||
/// <see cref="IDictionary"/> implementation. |
||||
/// </summary> |
||||
object GetValue(object message); |
||||
|
||||
/// <summary> |
||||
/// Mutator for single "simple" fields only. |
||||
/// </summary> |
||||
/// <remarks> |
||||
/// Repeated fields are mutated by fetching the value and manipulating it as a list. |
||||
/// Map fields are mutated by fetching the value and manipulating it as a dictionary. |
||||
/// </remarks> |
||||
/// <exception cref="InvalidOperationException">The field is not a "simple" field, or the message is frozen.</exception> |
||||
void SetValue(object message, object value); |
||||
} |
||||
} |
@ -1,173 +1,172 @@ |
||||
#region Copyright notice and license |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2008 Google Inc. All rights reserved. |
||||
// https://developers.google.com/protocol-buffers/ |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
#endregion |
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using Google.Protobuf.DescriptorProtos; |
||||
|
||||
namespace Google.Protobuf.Descriptors |
||||
{ |
||||
/// <summary> |
||||
/// Describes a message type. |
||||
/// </summary> |
||||
public sealed class MessageDescriptor : DescriptorBase |
||||
{ |
||||
private readonly DescriptorProto proto; |
||||
private readonly MessageDescriptor containingType; |
||||
private readonly IList<MessageDescriptor> nestedTypes; |
||||
private readonly IList<EnumDescriptor> enumTypes; |
||||
private readonly IList<FieldDescriptor> fields; |
||||
private readonly IList<OneofDescriptor> oneofs; |
||||
|
||||
internal MessageDescriptor(DescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int typeIndex) |
||||
: base(file, file.ComputeFullName(parent, proto.Name), typeIndex) |
||||
{ |
||||
this.proto = proto; |
||||
containingType = parent; |
||||
|
||||
oneofs = DescriptorUtil.ConvertAndMakeReadOnly(proto.OneofDecl, |
||||
(oneof, index) => |
||||
new OneofDescriptor(oneof, file, this, index)); |
||||
|
||||
nestedTypes = DescriptorUtil.ConvertAndMakeReadOnly(proto.NestedType, |
||||
(type, index) => |
||||
new MessageDescriptor(type, file, this, index)); |
||||
|
||||
enumTypes = DescriptorUtil.ConvertAndMakeReadOnly(proto.EnumType, |
||||
(type, index) => |
||||
new EnumDescriptor(type, file, this, index)); |
||||
|
||||
// TODO(jonskeet): Sort fields first? |
||||
fields = DescriptorUtil.ConvertAndMakeReadOnly(proto.Field, |
||||
(field, index) => |
||||
new FieldDescriptor(field, file, this, index)); |
||||
file.DescriptorPool.AddSymbol(this); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// The brief name of the descriptor's target. |
||||
/// </summary> |
||||
public override string Name { get { return proto.Name; } } |
||||
|
||||
internal DescriptorProto Proto { get { return proto; } } |
||||
|
||||
/// <value> |
||||
/// If this is a nested type, get the outer descriptor, otherwise null. |
||||
/// </value> |
||||
public MessageDescriptor ContainingType |
||||
{ |
||||
get { return containingType; } |
||||
} |
||||
|
||||
/// <value> |
||||
/// An unmodifiable list of this message type's fields. |
||||
/// </value> |
||||
public IList<FieldDescriptor> Fields |
||||
{ |
||||
get { return fields; } |
||||
} |
||||
|
||||
/// <value> |
||||
/// An unmodifiable list of this message type's nested types. |
||||
/// </value> |
||||
public IList<MessageDescriptor> NestedTypes |
||||
{ |
||||
get { return nestedTypes; } |
||||
} |
||||
|
||||
/// <value> |
||||
/// An unmodifiable list of this message type's enum types. |
||||
/// </value> |
||||
public IList<EnumDescriptor> EnumTypes |
||||
{ |
||||
get { return enumTypes; } |
||||
} |
||||
|
||||
public IList<OneofDescriptor> Oneofs |
||||
{ |
||||
get { return oneofs; } |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Finds a field by field name. |
||||
/// </summary> |
||||
/// <param name="name">The unqualified name of the field (e.g. "foo").</param> |
||||
/// <returns>The field's descriptor, or null if not found.</returns> |
||||
public FieldDescriptor FindFieldByName(String name) |
||||
{ |
||||
return File.DescriptorPool.FindSymbol<FieldDescriptor>(FullName + "." + name); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Finds a field by field number. |
||||
/// </summary> |
||||
/// <param name="number">The field number within this message type.</param> |
||||
/// <returns>The field's descriptor, or null if not found.</returns> |
||||
public FieldDescriptor FindFieldByNumber(int number) |
||||
{ |
||||
return File.DescriptorPool.FindFieldByNumber(this, number); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Finds a nested descriptor by name. The is valid for fields, nested |
||||
/// message types, oneofs and enums. |
||||
/// </summary> |
||||
/// <param name="name">The unqualified name of the descriptor, e.g. "Foo"</param> |
||||
/// <returns>The descriptor, or null if not found.</returns> |
||||
public T FindDescriptor<T>(string name) |
||||
where T : class, IDescriptor |
||||
{ |
||||
return File.DescriptorPool.FindSymbol<T>(FullName + "." + name); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Looks up and cross-links all fields and nested types. |
||||
/// </summary> |
||||
internal void CrossLink() |
||||
{ |
||||
foreach (MessageDescriptor message in nestedTypes) |
||||
{ |
||||
message.CrossLink(); |
||||
} |
||||
|
||||
foreach (FieldDescriptor field in fields) |
||||
{ |
||||
field.CrossLink(); |
||||
} |
||||
|
||||
foreach (OneofDescriptor oneof in oneofs) |
||||
{ |
||||
oneof.CrossLink(); |
||||
} |
||||
} |
||||
} |
||||
#region Copyright notice and license |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2008 Google Inc. All rights reserved. |
||||
// https://developers.google.com/protocol-buffers/ |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
#endregion |
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
|
||||
namespace Google.Protobuf.Reflection |
||||
{ |
||||
/// <summary> |
||||
/// Describes a message type. |
||||
/// </summary> |
||||
public sealed class MessageDescriptor : DescriptorBase |
||||
{ |
||||
private readonly DescriptorProto proto; |
||||
private readonly MessageDescriptor containingType; |
||||
private readonly IList<MessageDescriptor> nestedTypes; |
||||
private readonly IList<EnumDescriptor> enumTypes; |
||||
private readonly IList<FieldDescriptor> fields; |
||||
private readonly IList<OneofDescriptor> oneofs; |
||||
|
||||
internal MessageDescriptor(DescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int typeIndex) |
||||
: base(file, file.ComputeFullName(parent, proto.Name), typeIndex) |
||||
{ |
||||
this.proto = proto; |
||||
containingType = parent; |
||||
|
||||
oneofs = DescriptorUtil.ConvertAndMakeReadOnly(proto.OneofDecl, |
||||
(oneof, index) => |
||||
new OneofDescriptor(oneof, file, this, index)); |
||||
|
||||
nestedTypes = DescriptorUtil.ConvertAndMakeReadOnly(proto.NestedType, |
||||
(type, index) => |
||||
new MessageDescriptor(type, file, this, index)); |
||||
|
||||
enumTypes = DescriptorUtil.ConvertAndMakeReadOnly(proto.EnumType, |
||||
(type, index) => |
||||
new EnumDescriptor(type, file, this, index)); |
||||
|
||||
// TODO(jonskeet): Sort fields first? |
||||
fields = DescriptorUtil.ConvertAndMakeReadOnly(proto.Field, |
||||
(field, index) => |
||||
new FieldDescriptor(field, file, this, index)); |
||||
file.DescriptorPool.AddSymbol(this); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// The brief name of the descriptor's target. |
||||
/// </summary> |
||||
public override string Name { get { return proto.Name; } } |
||||
|
||||
internal DescriptorProto Proto { get { return proto; } } |
||||
|
||||
/// <value> |
||||
/// If this is a nested type, get the outer descriptor, otherwise null. |
||||
/// </value> |
||||
public MessageDescriptor ContainingType |
||||
{ |
||||
get { return containingType; } |
||||
} |
||||
|
||||
/// <value> |
||||
/// An unmodifiable list of this message type's fields. |
||||
/// </value> |
||||
public IList<FieldDescriptor> Fields |
||||
{ |
||||
get { return fields; } |
||||
} |
||||
|
||||
/// <value> |
||||
/// An unmodifiable list of this message type's nested types. |
||||
/// </value> |
||||
public IList<MessageDescriptor> NestedTypes |
||||
{ |
||||
get { return nestedTypes; } |
||||
} |
||||
|
||||
/// <value> |
||||
/// An unmodifiable list of this message type's enum types. |
||||
/// </value> |
||||
public IList<EnumDescriptor> EnumTypes |
||||
{ |
||||
get { return enumTypes; } |
||||
} |
||||
|
||||
public IList<OneofDescriptor> Oneofs |
||||
{ |
||||
get { return oneofs; } |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Finds a field by field name. |
||||
/// </summary> |
||||
/// <param name="name">The unqualified name of the field (e.g. "foo").</param> |
||||
/// <returns>The field's descriptor, or null if not found.</returns> |
||||
public FieldDescriptor FindFieldByName(String name) |
||||
{ |
||||
return File.DescriptorPool.FindSymbol<FieldDescriptor>(FullName + "." + name); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Finds a field by field number. |
||||
/// </summary> |
||||
/// <param name="number">The field number within this message type.</param> |
||||
/// <returns>The field's descriptor, or null if not found.</returns> |
||||
public FieldDescriptor FindFieldByNumber(int number) |
||||
{ |
||||
return File.DescriptorPool.FindFieldByNumber(this, number); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Finds a nested descriptor by name. The is valid for fields, nested |
||||
/// message types, oneofs and enums. |
||||
/// </summary> |
||||
/// <param name="name">The unqualified name of the descriptor, e.g. "Foo"</param> |
||||
/// <returns>The descriptor, or null if not found.</returns> |
||||
public T FindDescriptor<T>(string name) |
||||
where T : class, IDescriptor |
||||
{ |
||||
return File.DescriptorPool.FindSymbol<T>(FullName + "." + name); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Looks up and cross-links all fields and nested types. |
||||
/// </summary> |
||||
internal void CrossLink() |
||||
{ |
||||
foreach (MessageDescriptor message in nestedTypes) |
||||
{ |
||||
message.CrossLink(); |
||||
} |
||||
|
||||
foreach (FieldDescriptor field in fields) |
||||
{ |
||||
field.CrossLink(); |
||||
} |
||||
|
||||
foreach (OneofDescriptor oneof in oneofs) |
||||
{ |
||||
oneof.CrossLink(); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -1,95 +1,93 @@ |
||||
#region Copyright notice and license |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2008 Google Inc. All rights reserved. |
||||
// https://developers.google.com/protocol-buffers/ |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
#endregion |
||||
|
||||
using Google.Protobuf.DescriptorProtos; |
||||
|
||||
namespace Google.Protobuf.Descriptors |
||||
{ |
||||
/// <summary> |
||||
/// Describes a single method in a service. |
||||
/// </summary> |
||||
public sealed class MethodDescriptor : DescriptorBase |
||||
{ |
||||
private readonly MethodDescriptorProto proto; |
||||
private readonly ServiceDescriptor service; |
||||
private MessageDescriptor inputType; |
||||
private MessageDescriptor outputType; |
||||
|
||||
/// <value> |
||||
/// The service this method belongs to. |
||||
/// </value> |
||||
public ServiceDescriptor Service { get { return service; } } |
||||
|
||||
/// <value> |
||||
/// The method's input type. |
||||
/// </value> |
||||
public MessageDescriptor InputType { get { return inputType; } } |
||||
|
||||
/// <value> |
||||
/// The method's input type. |
||||
/// </value> |
||||
public MessageDescriptor OutputType { get { return outputType; } } |
||||
|
||||
internal MethodDescriptor(MethodDescriptorProto proto, FileDescriptor file, |
||||
ServiceDescriptor parent, int index) |
||||
: base(file, parent.FullName + "." + proto.Name, index) |
||||
{ |
||||
this.proto = proto; |
||||
service = parent; |
||||
file.DescriptorPool.AddSymbol(this); |
||||
} |
||||
|
||||
internal MethodDescriptorProto Proto { get { return proto; } } |
||||
|
||||
/// <summary> |
||||
/// The brief name of the descriptor's target. |
||||
/// </summary> |
||||
public override string Name { get { return proto.Name; } } |
||||
|
||||
internal void CrossLink() |
||||
{ |
||||
IDescriptor lookup = File.DescriptorPool.LookupSymbol(Proto.InputType, this); |
||||
if (!(lookup is MessageDescriptor)) |
||||
{ |
||||
throw new DescriptorValidationException(this, "\"" + Proto.InputType + "\" is not a message type."); |
||||
} |
||||
inputType = (MessageDescriptor) lookup; |
||||
|
||||
lookup = File.DescriptorPool.LookupSymbol(Proto.OutputType, this); |
||||
if (!(lookup is MessageDescriptor)) |
||||
{ |
||||
throw new DescriptorValidationException(this, "\"" + Proto.OutputType + "\" is not a message type."); |
||||
} |
||||
outputType = (MessageDescriptor) lookup; |
||||
} |
||||
} |
||||
#region Copyright notice and license |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2008 Google Inc. All rights reserved. |
||||
// https://developers.google.com/protocol-buffers/ |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
#endregion |
||||
|
||||
namespace Google.Protobuf.Reflection |
||||
{ |
||||
/// <summary> |
||||
/// Describes a single method in a service. |
||||
/// </summary> |
||||
public sealed class MethodDescriptor : DescriptorBase |
||||
{ |
||||
private readonly MethodDescriptorProto proto; |
||||
private readonly ServiceDescriptor service; |
||||
private MessageDescriptor inputType; |
||||
private MessageDescriptor outputType; |
||||
|
||||
/// <value> |
||||
/// The service this method belongs to. |
||||
/// </value> |
||||
public ServiceDescriptor Service { get { return service; } } |
||||
|
||||
/// <value> |
||||
/// The method's input type. |
||||
/// </value> |
||||
public MessageDescriptor InputType { get { return inputType; } } |
||||
|
||||
/// <value> |
||||
/// The method's input type. |
||||
/// </value> |
||||
public MessageDescriptor OutputType { get { return outputType; } } |
||||
|
||||
internal MethodDescriptor(MethodDescriptorProto proto, FileDescriptor file, |
||||
ServiceDescriptor parent, int index) |
||||
: base(file, parent.FullName + "." + proto.Name, index) |
||||
{ |
||||
this.proto = proto; |
||||
service = parent; |
||||
file.DescriptorPool.AddSymbol(this); |
||||
} |
||||
|
||||
internal MethodDescriptorProto Proto { get { return proto; } } |
||||
|
||||
/// <summary> |
||||
/// The brief name of the descriptor's target. |
||||
/// </summary> |
||||
public override string Name { get { return proto.Name; } } |
||||
|
||||
internal void CrossLink() |
||||
{ |
||||
IDescriptor lookup = File.DescriptorPool.LookupSymbol(Proto.InputType, this); |
||||
if (!(lookup is MessageDescriptor)) |
||||
{ |
||||
throw new DescriptorValidationException(this, "\"" + Proto.InputType + "\" is not a message type."); |
||||
} |
||||
inputType = (MessageDescriptor) lookup; |
||||
|
||||
lookup = File.DescriptorPool.LookupSymbol(Proto.OutputType, this); |
||||
if (!(lookup is MessageDescriptor)) |
||||
{ |
||||
throw new DescriptorValidationException(this, "\"" + Proto.OutputType + "\" is not a message type."); |
||||
} |
||||
outputType = (MessageDescriptor) lookup; |
||||
} |
||||
} |
||||
} |
@ -1,68 +1,68 @@ |
||||
#region Copyright notice and license |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2008 Google Inc. All rights reserved. |
||||
// https://developers.google.com/protocol-buffers/ |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
#endregion |
||||
|
||||
namespace Google.Protobuf.Descriptors |
||||
{ |
||||
/// <summary> |
||||
/// Represents a package in the symbol table. We use PackageDescriptors |
||||
/// just as placeholders so that someone cannot define, say, a message type |
||||
/// that has the same name as an existing package. |
||||
/// </summary> |
||||
internal sealed class PackageDescriptor : IDescriptor |
||||
{ |
||||
private readonly string name; |
||||
private readonly string fullName; |
||||
private readonly FileDescriptor file; |
||||
|
||||
internal PackageDescriptor(string name, string fullName, FileDescriptor file) |
||||
{ |
||||
this.file = file; |
||||
this.fullName = fullName; |
||||
this.name = name; |
||||
} |
||||
|
||||
public string Name |
||||
{ |
||||
get { return name; } |
||||
} |
||||
|
||||
public string FullName |
||||
{ |
||||
get { return fullName; } |
||||
} |
||||
|
||||
public FileDescriptor File |
||||
{ |
||||
get { return file; } |
||||
} |
||||
} |
||||
#region Copyright notice and license |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2008 Google Inc. All rights reserved. |
||||
// https://developers.google.com/protocol-buffers/ |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
#endregion |
||||
|
||||
namespace Google.Protobuf.Reflection |
||||
{ |
||||
/// <summary> |
||||
/// Represents a package in the symbol table. We use PackageDescriptors |
||||
/// just as placeholders so that someone cannot define, say, a message type |
||||
/// that has the same name as an existing package. |
||||
/// </summary> |
||||
internal sealed class PackageDescriptor : IDescriptor |
||||
{ |
||||
private readonly string name; |
||||
private readonly string fullName; |
||||
private readonly FileDescriptor file; |
||||
|
||||
internal PackageDescriptor(string name, string fullName, FileDescriptor file) |
||||
{ |
||||
this.file = file; |
||||
this.fullName = fullName; |
||||
this.name = name; |
||||
} |
||||
|
||||
public string Name |
||||
{ |
||||
get { return name; } |
||||
} |
||||
|
||||
public string FullName |
||||
{ |
||||
get { return fullName; } |
||||
} |
||||
|
||||
public FileDescriptor File |
||||
{ |
||||
get { return file; } |
||||
} |
||||
} |
||||
} |
@ -1,106 +1,106 @@ |
||||
#region Copyright notice and license |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2008 Google Inc. All rights reserved. |
||||
// https://developers.google.com/protocol-buffers/ |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
#endregion |
||||
|
||||
using System; |
||||
using System.Linq.Expressions; |
||||
using System.Reflection; |
||||
|
||||
namespace Google.Protobuf.FieldAccess |
||||
{ |
||||
/// <summary> |
||||
/// The methods in this class are somewhat evil, and should not be tampered with lightly. |
||||
/// Basically they allow the creation of relatively weakly typed delegates from MethodInfos |
||||
/// which are more strongly typed. They do this by creating an appropriate strongly typed |
||||
/// delegate from the MethodInfo, and then calling that within an anonymous method. |
||||
/// Mind-bending stuff (at least to your humble narrator) but the resulting delegates are |
||||
/// very fast compared with calling Invoke later on. |
||||
/// </summary> |
||||
internal static class ReflectionUtil |
||||
{ |
||||
/// <summary> |
||||
/// Empty Type[] used when calling GetProperty to force property instead of indexer fetching. |
||||
/// </summary> |
||||
internal static readonly Type[] EmptyTypes = new Type[0]; |
||||
|
||||
/// <summary> |
||||
/// Creates a delegate which will cast the argument to the appropriate method target type, |
||||
/// call the method on it, then convert the result to object. |
||||
/// </summary> |
||||
internal static Func<object, object> CreateFuncObjectObject(MethodInfo method) |
||||
{ |
||||
ParameterExpression parameter = Expression.Parameter(typeof(object), "p"); |
||||
Expression downcast = Expression.Convert(parameter, method.DeclaringType); |
||||
Expression call = Expression.Call(downcast, method); |
||||
Expression upcast = Expression.Convert(call, typeof(object)); |
||||
return Expression.Lambda<Func<object, object>>(upcast, parameter).Compile(); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Creates a delegate which will cast the argument to the appropriate method target type, |
||||
/// call the method on it, then convert the result to the specified type. |
||||
/// </summary> |
||||
internal static Func<object, T> CreateFuncObjectT<T>(MethodInfo method) |
||||
{ |
||||
ParameterExpression parameter = Expression.Parameter(typeof(object), "p"); |
||||
Expression downcast = Expression.Convert(parameter, method.DeclaringType); |
||||
Expression call = Expression.Call(downcast, method); |
||||
Expression upcast = Expression.Convert(call, typeof(T)); |
||||
return Expression.Lambda<Func<object, T>>(upcast, parameter).Compile(); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Creates a delegate which will execute the given method after casting the first argument to |
||||
/// the target type of the method, and the second argument to the first parameter type of the method. |
||||
/// </summary> |
||||
internal static Action<object, object> CreateActionObjectObject(MethodInfo method) |
||||
{ |
||||
ParameterExpression targetParameter = Expression.Parameter(typeof(object), "target"); |
||||
ParameterExpression argParameter = Expression.Parameter(typeof(object), "arg"); |
||||
Expression castTarget = Expression.Convert(targetParameter, method.DeclaringType); |
||||
Expression castArgument = Expression.Convert(argParameter, method.GetParameters()[0].ParameterType); |
||||
Expression call = Expression.Call(castTarget, method, castArgument); |
||||
return Expression.Lambda<Action<object, object>>(call, targetParameter, argParameter).Compile(); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Creates a delegate which will execute the given method after casting the first argument to |
||||
/// the target type of the method. |
||||
/// </summary> |
||||
internal static Action<object> CreateActionObject(MethodInfo method) |
||||
{ |
||||
ParameterExpression targetParameter = Expression.Parameter(typeof(object), "target"); |
||||
Expression castTarget = Expression.Convert(targetParameter, method.DeclaringType); |
||||
Expression call = Expression.Call(castTarget, method); |
||||
return Expression.Lambda<Action<object>>(call, targetParameter).Compile(); |
||||
} |
||||
} |
||||
#region Copyright notice and license |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2008 Google Inc. All rights reserved. |
||||
// https://developers.google.com/protocol-buffers/ |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
#endregion |
||||
|
||||
using System; |
||||
using System.Linq.Expressions; |
||||
using System.Reflection; |
||||
|
||||
namespace Google.Protobuf.Reflection |
||||
{ |
||||
/// <summary> |
||||
/// The methods in this class are somewhat evil, and should not be tampered with lightly. |
||||
/// Basically they allow the creation of relatively weakly typed delegates from MethodInfos |
||||
/// which are more strongly typed. They do this by creating an appropriate strongly typed |
||||
/// delegate from the MethodInfo, and then calling that within an anonymous method. |
||||
/// Mind-bending stuff (at least to your humble narrator) but the resulting delegates are |
||||
/// very fast compared with calling Invoke later on. |
||||
/// </summary> |
||||
internal static class ReflectionUtil |
||||
{ |
||||
/// <summary> |
||||
/// Empty Type[] used when calling GetProperty to force property instead of indexer fetching. |
||||
/// </summary> |
||||
internal static readonly Type[] EmptyTypes = new Type[0]; |
||||
|
||||
/// <summary> |
||||
/// Creates a delegate which will cast the argument to the appropriate method target type, |
||||
/// call the method on it, then convert the result to object. |
||||
/// </summary> |
||||
internal static Func<object, object> CreateFuncObjectObject(MethodInfo method) |
||||
{ |
||||
ParameterExpression parameter = Expression.Parameter(typeof(object), "p"); |
||||
Expression downcast = Expression.Convert(parameter, method.DeclaringType); |
||||
Expression call = Expression.Call(downcast, method); |
||||
Expression upcast = Expression.Convert(call, typeof(object)); |
||||
return Expression.Lambda<Func<object, object>>(upcast, parameter).Compile(); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Creates a delegate which will cast the argument to the appropriate method target type, |
||||
/// call the method on it, then convert the result to the specified type. |
||||
/// </summary> |
||||
internal static Func<object, T> CreateFuncObjectT<T>(MethodInfo method) |
||||
{ |
||||
ParameterExpression parameter = Expression.Parameter(typeof(object), "p"); |
||||
Expression downcast = Expression.Convert(parameter, method.DeclaringType); |
||||
Expression call = Expression.Call(downcast, method); |
||||
Expression upcast = Expression.Convert(call, typeof(T)); |
||||
return Expression.Lambda<Func<object, T>>(upcast, parameter).Compile(); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Creates a delegate which will execute the given method after casting the first argument to |
||||
/// the target type of the method, and the second argument to the first parameter type of the method. |
||||
/// </summary> |
||||
internal static Action<object, object> CreateActionObjectObject(MethodInfo method) |
||||
{ |
||||
ParameterExpression targetParameter = Expression.Parameter(typeof(object), "target"); |
||||
ParameterExpression argParameter = Expression.Parameter(typeof(object), "arg"); |
||||
Expression castTarget = Expression.Convert(targetParameter, method.DeclaringType); |
||||
Expression castArgument = Expression.Convert(argParameter, method.GetParameters()[0].ParameterType); |
||||
Expression call = Expression.Call(castTarget, method, castArgument); |
||||
return Expression.Lambda<Action<object, object>>(call, targetParameter, argParameter).Compile(); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Creates a delegate which will execute the given method after casting the first argument to |
||||
/// the target type of the method. |
||||
/// </summary> |
||||
internal static Action<object> CreateActionObject(MethodInfo method) |
||||
{ |
||||
ParameterExpression targetParameter = Expression.Parameter(typeof(object), "target"); |
||||
Expression castTarget = Expression.Convert(targetParameter, method.DeclaringType); |
||||
Expression call = Expression.Call(castTarget, method); |
||||
return Expression.Lambda<Action<object>>(call, targetParameter).Compile(); |
||||
} |
||||
} |
||||
} |
@ -1,90 +1,89 @@ |
||||
#region Copyright notice and license |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2008 Google Inc. All rights reserved. |
||||
// https://developers.google.com/protocol-buffers/ |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
#endregion |
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using Google.Protobuf.DescriptorProtos; |
||||
|
||||
namespace Google.Protobuf.Descriptors |
||||
{ |
||||
/// <summary> |
||||
/// Describes a service type. |
||||
/// </summary> |
||||
public sealed class ServiceDescriptor : DescriptorBase |
||||
{ |
||||
private readonly ServiceDescriptorProto proto; |
||||
private readonly IList<MethodDescriptor> methods; |
||||
|
||||
internal ServiceDescriptor(ServiceDescriptorProto proto, FileDescriptor file, int index) |
||||
: base(file, file.ComputeFullName(null, proto.Name), index) |
||||
{ |
||||
this.proto = proto; |
||||
methods = DescriptorUtil.ConvertAndMakeReadOnly(proto.Method, |
||||
(method, i) => new MethodDescriptor(method, file, this, i)); |
||||
|
||||
file.DescriptorPool.AddSymbol(this); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// The brief name of the descriptor's target. |
||||
/// </summary> |
||||
public override string Name { get { return proto.Name; } } |
||||
|
||||
internal ServiceDescriptorProto Proto { get { return proto; } } |
||||
|
||||
/// <value> |
||||
/// An unmodifiable list of methods in this service. |
||||
/// </value> |
||||
public IList<MethodDescriptor> Methods |
||||
{ |
||||
get { return methods; } |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Finds a method by name. |
||||
/// </summary> |
||||
/// <param name="name">The unqualified name of the method (e.g. "Foo").</param> |
||||
/// <returns>The method's decsriptor, or null if not found.</returns> |
||||
public MethodDescriptor FindMethodByName(String name) |
||||
{ |
||||
return File.DescriptorPool.FindSymbol<MethodDescriptor>(FullName + "." + name); |
||||
} |
||||
|
||||
internal void CrossLink() |
||||
{ |
||||
foreach (MethodDescriptor method in methods) |
||||
{ |
||||
method.CrossLink(); |
||||
} |
||||
} |
||||
} |
||||
#region Copyright notice and license |
||||
// Protocol Buffers - Google's data interchange format |
||||
// Copyright 2008 Google Inc. All rights reserved. |
||||
// https://developers.google.com/protocol-buffers/ |
||||
// |
||||
// Redistribution and use in source and binary forms, with or without |
||||
// modification, are permitted provided that the following conditions are |
||||
// met: |
||||
// |
||||
// * Redistributions of source code must retain the above copyright |
||||
// notice, this list of conditions and the following disclaimer. |
||||
// * Redistributions in binary form must reproduce the above |
||||
// copyright notice, this list of conditions and the following disclaimer |
||||
// in the documentation and/or other materials provided with the |
||||
// distribution. |
||||
// * Neither the name of Google Inc. nor the names of its |
||||
// contributors may be used to endorse or promote products derived from |
||||
// this software without specific prior written permission. |
||||
// |
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
#endregion |
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
|
||||
namespace Google.Protobuf.Reflection |
||||
{ |
||||
/// <summary> |
||||
/// Describes a service type. |
||||
/// </summary> |
||||
public sealed class ServiceDescriptor : DescriptorBase |
||||
{ |
||||
private readonly ServiceDescriptorProto proto; |
||||
private readonly IList<MethodDescriptor> methods; |
||||
|
||||
internal ServiceDescriptor(ServiceDescriptorProto proto, FileDescriptor file, int index) |
||||
: base(file, file.ComputeFullName(null, proto.Name), index) |
||||
{ |
||||
this.proto = proto; |
||||
methods = DescriptorUtil.ConvertAndMakeReadOnly(proto.Method, |
||||
(method, i) => new MethodDescriptor(method, file, this, i)); |
||||
|
||||
file.DescriptorPool.AddSymbol(this); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// The brief name of the descriptor's target. |
||||
/// </summary> |
||||
public override string Name { get { return proto.Name; } } |
||||
|
||||
internal ServiceDescriptorProto Proto { get { return proto; } } |
||||
|
||||
/// <value> |
||||
/// An unmodifiable list of methods in this service. |
||||
/// </value> |
||||
public IList<MethodDescriptor> Methods |
||||
{ |
||||
get { return methods; } |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Finds a method by name. |
||||
/// </summary> |
||||
/// <param name="name">The unqualified name of the method (e.g. "Foo").</param> |
||||
/// <returns>The method's decsriptor, or null if not found.</returns> |
||||
public MethodDescriptor FindMethodByName(String name) |
||||
{ |
||||
return File.DescriptorPool.FindSymbol<MethodDescriptor>(FullName + "." + name); |
||||
} |
||||
|
||||
internal void CrossLink() |
||||
{ |
||||
foreach (MethodDescriptor method in methods) |
||||
{ |
||||
method.CrossLink(); |
||||
} |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue