Commit 9f37de96 authored by Jon Skeet's avatar Jon Skeet

Changing reflection namespace (part 1)

- Move types into Google.Protobuf.Reflection
- Change codegen to reflect that in generated types

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