Fix descriptor reflection in various ways
- The protos are no longer publicly exposed at all - Oneof detection now works (as we default to -1, not 0) - OneofDescriptor exposes the fields in the oneof - Removed unnecessary code for replacing protos - remnant of extensions - There's now just the non-generic form of IDescriptor
This commit is contained in:
parent
5350822b0a
commit
af259b77bf
@ -30,6 +30,8 @@
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#endregion
|
||||
|
||||
using System.Linq;
|
||||
using Google.Protobuf.DescriptorProtos;
|
||||
using Google.Protobuf.Descriptors;
|
||||
using Google.Protobuf.TestProtos;
|
||||
using NUnit.Framework;
|
||||
@ -50,7 +52,7 @@ namespace Google.Protobuf
|
||||
Assert.AreEqual("google/protobuf/unittest_proto3.proto", file.Name);
|
||||
Assert.AreEqual("protobuf_unittest", file.Package);
|
||||
|
||||
Assert.AreEqual("UnittestProto", file.Options.JavaOuterClassname);
|
||||
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.
|
||||
@ -92,7 +94,7 @@ namespace Google.Protobuf
|
||||
Assert.AreEqual("protobuf_unittest.TestAllTypes", messageType.FullName);
|
||||
Assert.AreEqual(UnittestProto3.Descriptor, messageType.File);
|
||||
Assert.IsNull(messageType.ContainingType);
|
||||
Assert.IsNull(messageType.Options);
|
||||
Assert.IsNull(messageType.Proto.Options);
|
||||
|
||||
Assert.AreEqual("TestAllTypes", messageType.Name);
|
||||
|
||||
@ -143,7 +145,7 @@ namespace Google.Protobuf
|
||||
Assert.AreEqual(messageType, primitiveField.ContainingType);
|
||||
Assert.AreEqual(UnittestProto3.Descriptor, primitiveField.File);
|
||||
Assert.AreEqual(FieldType.Int32, primitiveField.FieldType);
|
||||
Assert.IsNull(primitiveField.Options);
|
||||
Assert.IsNull(primitiveField.Proto.Options);
|
||||
|
||||
Assert.AreEqual("single_nested_enum", enumField.Name);
|
||||
Assert.AreEqual(FieldType.Enum, enumField.FieldType);
|
||||
@ -177,7 +179,7 @@ namespace Google.Protobuf
|
||||
Assert.AreEqual("protobuf_unittest.ForeignEnum", enumType.FullName);
|
||||
Assert.AreEqual(UnittestProto3.Descriptor, enumType.File);
|
||||
Assert.Null(enumType.ContainingType);
|
||||
Assert.Null(enumType.Options);
|
||||
Assert.Null(enumType.Proto.Options);
|
||||
|
||||
Assert.AreEqual("NestedEnum", nestedType.Name);
|
||||
Assert.AreEqual("protobuf_unittest.TestAllTypes.NestedEnum",
|
||||
@ -197,5 +199,27 @@ namespace Google.Protobuf
|
||||
Assert.AreEqual(i, enumType.Values[i].Index);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OneofDescriptor()
|
||||
{
|
||||
OneofDescriptor descriptor = TestAllTypes.Descriptor.FindDescriptor<OneofDescriptor>("oneof_field");
|
||||
Assert.AreEqual("oneof_field", descriptor.Name);
|
||||
Assert.AreEqual("protobuf_unittest.TestAllTypes.oneof_field", descriptor.FullName);
|
||||
|
||||
var expectedFields = new[] {
|
||||
TestAllTypes.OneofBytesFieldNumber,
|
||||
TestAllTypes.OneofNestedMessageFieldNumber,
|
||||
TestAllTypes.OneofStringFieldNumber,
|
||||
TestAllTypes.OneofUint32FieldNumber }
|
||||
.Select(fieldNumber => TestAllTypes.Descriptor.FindFieldByNumber(fieldNumber))
|
||||
.ToList();
|
||||
foreach (var field in expectedFields)
|
||||
{
|
||||
Assert.AreSame(descriptor, field.ContainingOneof);
|
||||
}
|
||||
|
||||
CollectionAssert.AreEquivalent(expectedFields, descriptor.Fields);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
#region Copyright notice and license
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#endregion
|
||||
|
||||
namespace Google.Protobuf.DescriptorProtos
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface implemented by all DescriptorProtos. The generator doesn't
|
||||
/// emit the interface implementation claim, so PartialClasses.cs contains
|
||||
/// partial class declarations for each of them.
|
||||
/// </summary>
|
||||
/// <typeparam name="TOptions">The associated options protocol buffer type</typeparam>
|
||||
public interface IDescriptorProto<TOptions>
|
||||
{
|
||||
/// <summary>
|
||||
/// The brief name of the descriptor's target.
|
||||
/// </summary>
|
||||
string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The options for this descriptor.
|
||||
/// </summary>
|
||||
TOptions Options { get; }
|
||||
}
|
||||
}
|
@ -30,36 +30,18 @@
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#endregion
|
||||
|
||||
// This file just contains partial classes for each of the
|
||||
// autogenerated classes, so that they implement
|
||||
// IDescriptorProto
|
||||
// This file just contains partial classes for any autogenerated classes that need additional support.
|
||||
namespace Google.Protobuf.DescriptorProtos
|
||||
{
|
||||
public partial class DescriptorProto : IDescriptorProto<MessageOptions>
|
||||
{
|
||||
}
|
||||
|
||||
public partial class EnumDescriptorProto : IDescriptorProto<EnumOptions>
|
||||
{
|
||||
}
|
||||
|
||||
public partial class EnumValueDescriptorProto : IDescriptorProto<EnumValueOptions>
|
||||
{
|
||||
}
|
||||
|
||||
public partial class FieldDescriptorProto : IDescriptorProto<FieldOptions>
|
||||
{
|
||||
}
|
||||
|
||||
public partial class FileDescriptorProto : IDescriptorProto<FileOptions>
|
||||
{
|
||||
}
|
||||
|
||||
public partial class MethodDescriptorProto : IDescriptorProto<MethodOptions>
|
||||
{
|
||||
}
|
||||
|
||||
public partial class ServiceDescriptorProto : IDescriptorProto<ServiceOptions>
|
||||
internal partial class FieldDescriptorProto
|
||||
{
|
||||
// We can't tell the difference between "explicitly set to 0" and "not set"
|
||||
// in proto3, but we need to tell the difference for OneofIndex. descriptor.proto
|
||||
// is really a proto2 file, but the runtime doesn't know about proto2 semantics...
|
||||
// We fake it by defaulting to -1.
|
||||
partial void OnConstruction()
|
||||
{
|
||||
OneofIndex = -1;
|
||||
}
|
||||
}
|
||||
}
|
@ -34,61 +34,36 @@ using Google.Protobuf.DescriptorProtos;
|
||||
|
||||
namespace Google.Protobuf.Descriptors
|
||||
{
|
||||
// TODO(jonskeet): The descriptor type hierarchy needs changing so that we can hide the descriptor protos.
|
||||
/// <summary>
|
||||
/// Base class for nearly all descriptors, providing common functionality.
|
||||
/// </summary>
|
||||
/// <typeparam name="TProto">Type of the protocol buffer form of this descriptor</typeparam>
|
||||
/// <typeparam name="TOptions">Type of the options protocol buffer for this descriptor</typeparam>
|
||||
public abstract class DescriptorBase<TProto, TOptions> : IDescriptor<TProto>
|
||||
where TProto : IMessage, IDescriptorProto<TOptions>
|
||||
public abstract class DescriptorBase : IDescriptor
|
||||
{
|
||||
private TProto proto;
|
||||
private readonly FileDescriptor file;
|
||||
private readonly string fullName;
|
||||
private readonly int index;
|
||||
|
||||
protected DescriptorBase(TProto proto, FileDescriptor file, string fullName)
|
||||
internal DescriptorBase(FileDescriptor file, string fullName, int index)
|
||||
{
|
||||
this.proto = proto;
|
||||
this.file = file;
|
||||
this.fullName = fullName;
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
internal virtual void ReplaceProto(TProto newProto)
|
||||
/// <value>
|
||||
/// The index of this descriptor within its parent descriptor.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// This returns the index of this descriptor within its parent, for
|
||||
/// this descriptor's type. (There can be duplicate values for different
|
||||
/// types, e.g. one enum type with index 0 and one message type with index 0.)
|
||||
/// </remarks>
|
||||
public int Index
|
||||
{
|
||||
this.proto = newProto;
|
||||
get { return index; }
|
||||
}
|
||||
|
||||
protected static string ComputeFullName(FileDescriptor file, MessageDescriptor parent, string name)
|
||||
{
|
||||
if (parent != null)
|
||||
{
|
||||
return parent.FullName + "." + name;
|
||||
}
|
||||
if (file.Package.Length > 0)
|
||||
{
|
||||
return file.Package + "." + name;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
IMessage IDescriptor.Proto
|
||||
{
|
||||
get { return proto; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the protocol buffer form of this descriptor.
|
||||
/// </summary>
|
||||
public TProto Proto
|
||||
{
|
||||
get { return proto; }
|
||||
}
|
||||
|
||||
public TOptions Options
|
||||
{
|
||||
get { return proto.Options; }
|
||||
}
|
||||
public abstract string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The fully qualified name of the descriptor's target.
|
||||
@ -98,14 +73,6 @@ namespace Google.Protobuf.Descriptors
|
||||
get { return fullName; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The brief name of the descriptor's target.
|
||||
/// </summary>
|
||||
public string Name
|
||||
{
|
||||
get { return proto.Name; }
|
||||
}
|
||||
|
||||
/// <value>
|
||||
/// The file this descriptor was declared in.
|
||||
/// </value>
|
||||
|
@ -257,7 +257,7 @@ namespace Google.Protobuf.Descriptors
|
||||
/// or unqualified. C++-like name lookup semantics are used to search for the
|
||||
/// matching descriptor.
|
||||
/// </summary>
|
||||
public IDescriptor LookupSymbol(string name, IDescriptor relativeTo)
|
||||
internal IDescriptor LookupSymbol(string name, IDescriptor relativeTo)
|
||||
{
|
||||
// TODO(jonskeet): This could be optimized in a number of ways.
|
||||
|
||||
|
@ -38,14 +38,16 @@ namespace Google.Protobuf.Descriptors
|
||||
/// <summary>
|
||||
/// Descriptor for an enum type in a .proto file.
|
||||
/// </summary>
|
||||
public sealed class EnumDescriptor : IndexedDescriptorBase<EnumDescriptorProto, EnumOptions>
|
||||
public sealed class EnumDescriptor : DescriptorBase
|
||||
{
|
||||
private readonly EnumDescriptorProto proto;
|
||||
private readonly MessageDescriptor containingType;
|
||||
private readonly IList<EnumValueDescriptor> values;
|
||||
|
||||
internal EnumDescriptor(EnumDescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int index)
|
||||
: base(proto, file, ComputeFullName(file, parent, proto.Name), index)
|
||||
: base(file, file.ComputeFullName(parent, proto.Name), index)
|
||||
{
|
||||
this.proto = proto;
|
||||
containingType = parent;
|
||||
|
||||
if (proto.Value.Count == 0)
|
||||
@ -61,6 +63,13 @@ namespace Google.Protobuf.Descriptors
|
||||
File.DescriptorPool.AddSymbol(this);
|
||||
}
|
||||
|
||||
internal EnumDescriptorProto Proto { get { return proto; } }
|
||||
|
||||
/// <summary>
|
||||
/// The brief name of the descriptor's target.
|
||||
/// </summary>
|
||||
public override string Name { get { return proto.Name; } }
|
||||
|
||||
/// <value>
|
||||
/// If this is a nested type, get the outer descriptor, otherwise null.
|
||||
/// </value>
|
||||
@ -95,14 +104,5 @@ namespace Google.Protobuf.Descriptors
|
||||
{
|
||||
return File.DescriptorPool.FindSymbol<EnumValueDescriptor>(FullName + "." + name);
|
||||
}
|
||||
|
||||
internal override void ReplaceProto(EnumDescriptorProto newProto)
|
||||
{
|
||||
base.ReplaceProto(newProto);
|
||||
for (int i = 0; i < values.Count; i++)
|
||||
{
|
||||
values[i].ReplaceProto(newProto.Value[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -37,27 +37,27 @@ namespace Google.Protobuf.Descriptors
|
||||
/// <summary>
|
||||
/// Descriptor for a single enum value within an enum in a .proto file.
|
||||
/// </summary>
|
||||
public sealed class EnumValueDescriptor : IndexedDescriptorBase<EnumValueDescriptorProto, EnumValueOptions>
|
||||
public sealed class EnumValueDescriptor : DescriptorBase
|
||||
{
|
||||
private readonly EnumDescriptor enumDescriptor;
|
||||
private readonly EnumValueDescriptorProto proto;
|
||||
|
||||
internal EnumValueDescriptor(EnumValueDescriptorProto proto, FileDescriptor file,
|
||||
EnumDescriptor parent, int index)
|
||||
: base(proto, file, parent.FullName + "." + proto.Name, index)
|
||||
: base(file, parent.FullName + "." + proto.Name, index)
|
||||
{
|
||||
this.proto = proto;
|
||||
enumDescriptor = parent;
|
||||
file.DescriptorPool.AddSymbol(this);
|
||||
file.DescriptorPool.AddEnumValueByNumber(this);
|
||||
}
|
||||
|
||||
public int Number
|
||||
{
|
||||
get { return Proto.Number; }
|
||||
}
|
||||
internal EnumValueDescriptorProto Proto { get { return proto; } }
|
||||
|
||||
public override string Name { get { return proto.Name; } }
|
||||
|
||||
public EnumDescriptor EnumDescriptor
|
||||
{
|
||||
get { return enumDescriptor; }
|
||||
}
|
||||
public int Number { get { return Proto.Number; } }
|
||||
|
||||
public EnumDescriptor EnumDescriptor { get { return enumDescriptor; } }
|
||||
}
|
||||
}
|
@ -38,21 +38,20 @@ namespace Google.Protobuf.Descriptors
|
||||
/// <summary>
|
||||
/// Descriptor for a field or extension within a message in a .proto file.
|
||||
/// </summary>
|
||||
public sealed class FieldDescriptor : IndexedDescriptorBase<FieldDescriptorProto, FieldOptions>,
|
||||
IComparable<FieldDescriptor>
|
||||
public sealed class FieldDescriptor : DescriptorBase, IComparable<FieldDescriptor>
|
||||
{
|
||||
private readonly FieldDescriptorProto proto;
|
||||
private EnumDescriptor enumType;
|
||||
private MessageDescriptor messageType;
|
||||
private MessageDescriptor containingType;
|
||||
private OneofDescriptor containingOneof;
|
||||
private readonly MessageDescriptor containingType;
|
||||
private readonly OneofDescriptor containingOneof;
|
||||
private FieldType fieldType;
|
||||
|
||||
private readonly object optionsLock = new object();
|
||||
|
||||
internal FieldDescriptor(FieldDescriptorProto proto, FileDescriptor file,
|
||||
MessageDescriptor parent, int index)
|
||||
: base(proto, file, ComputeFullName(file, parent, proto.Name), index)
|
||||
: base(file, file.ComputeFullName(parent, proto.Name), index)
|
||||
{
|
||||
this.proto = proto;
|
||||
if (proto.Type != 0)
|
||||
{
|
||||
fieldType = GetFieldTypeFromProtoType(proto.Type);
|
||||
@ -64,7 +63,8 @@ namespace Google.Protobuf.Descriptors
|
||||
"Field numbers must be positive integers.");
|
||||
}
|
||||
containingType = parent;
|
||||
if (proto.OneofIndex != 0)
|
||||
// OneofIndex "defaults" to -1 due to a hack in FieldDescriptor.OnConstruction.
|
||||
if (proto.OneofIndex != -1)
|
||||
{
|
||||
if (proto.OneofIndex < 0 || proto.OneofIndex >= parent.Proto.OneofDecl.Count)
|
||||
{
|
||||
@ -72,12 +72,18 @@ namespace Google.Protobuf.Descriptors
|
||||
"FieldDescriptorProto.oneof_index is out of range for type " + parent.Name);
|
||||
}
|
||||
containingOneof = parent.Oneofs[proto.OneofIndex];
|
||||
containingOneof.fieldCount ++;
|
||||
}
|
||||
|
||||
file.DescriptorPool.AddSymbol(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The brief name of the descriptor's target.
|
||||
/// </summary>
|
||||
public override string Name { get { return proto.Name; } }
|
||||
|
||||
internal FieldDescriptorProto Proto { get { return proto; } }
|
||||
|
||||
/// <summary>
|
||||
/// Maps a field type as included in the .proto file to a FieldType.
|
||||
/// </summary>
|
||||
@ -133,12 +139,12 @@ namespace Google.Protobuf.Descriptors
|
||||
|
||||
public bool IsMap
|
||||
{
|
||||
get { return fieldType == FieldType.Message && messageType.Options != null && messageType.Options.MapEntry; }
|
||||
get { return fieldType == FieldType.Message && messageType.Proto.Options != null && messageType.Proto.Options.MapEntry; }
|
||||
}
|
||||
|
||||
public bool IsPacked
|
||||
{
|
||||
get { return Proto.Options.Packed; }
|
||||
get { return Proto.Options != null && Proto.Options.Packed; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -278,7 +284,7 @@ namespace Google.Protobuf.Descriptors
|
||||
|
||||
File.DescriptorPool.AddFieldByNumber(this);
|
||||
|
||||
if (containingType != null && containingType.Options != null && containingType.Options.MessageSetWireFormat)
|
||||
if (containingType != null && containingType.Proto.Options != null && containingType.Proto.Options.MessageSetWireFormat)
|
||||
{
|
||||
throw new DescriptorValidationException(this, "MessageSet format is not supported.");
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ namespace Google.Protobuf.Descriptors
|
||||
/// IDescriptor is implemented such that the File property returns this descriptor,
|
||||
/// and the FullName is the same as the Name.
|
||||
/// </summary>
|
||||
public sealed class FileDescriptor : IDescriptor<FileDescriptorProto>
|
||||
public sealed class FileDescriptor : IDescriptor
|
||||
{
|
||||
private readonly FileDescriptorProto proto;
|
||||
private readonly IList<MessageDescriptor> messageTypes;
|
||||
@ -87,6 +87,22 @@ namespace Google.Protobuf.Descriptors
|
||||
new ServiceDescriptor(service, this, index));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Computes the full name of a descriptor within this file, with an optional parent message.
|
||||
/// </summary>
|
||||
internal string ComputeFullName(MessageDescriptor parent, string name)
|
||||
{
|
||||
if (parent != null)
|
||||
{
|
||||
return parent.FullName + "." + name;
|
||||
}
|
||||
if (Package.Length > 0)
|
||||
{
|
||||
return Package + "." + name;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extracts public dependencies from direct dependencies. This is a static method despite its
|
||||
/// first parameter, as the value we're in the middle of constructing is only used for exceptions.
|
||||
@ -127,19 +143,11 @@ namespace Google.Protobuf.Descriptors
|
||||
/// <value>
|
||||
/// The descriptor in its protocol message representation.
|
||||
/// </value>
|
||||
public FileDescriptorProto Proto
|
||||
internal FileDescriptorProto Proto
|
||||
{
|
||||
get { return proto; }
|
||||
}
|
||||
|
||||
/// <value>
|
||||
/// The <see cref="DescriptorProtos.FileOptions" /> defined in <c>descriptor.proto</c>.
|
||||
/// </value>
|
||||
public FileOptions Options
|
||||
{
|
||||
get { return proto.Options; }
|
||||
}
|
||||
|
||||
/// <value>
|
||||
/// The file name.
|
||||
/// </value>
|
||||
@ -213,14 +221,6 @@ namespace Google.Protobuf.Descriptors
|
||||
get { return this; }
|
||||
}
|
||||
|
||||
/// <value>
|
||||
/// Protocol buffer describing this descriptor.
|
||||
/// </value>
|
||||
IMessage IDescriptor.Proto
|
||||
{
|
||||
get { return Proto; }
|
||||
}
|
||||
|
||||
/// <value>
|
||||
/// Pool containing symbol descriptors.
|
||||
/// </value>
|
||||
@ -255,22 +255,7 @@ namespace Google.Protobuf.Descriptors
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Builds a FileDescriptor from its protocol buffer representation.
|
||||
/// </summary>
|
||||
/// <param name="proto">The protocol message form of the FileDescriptor.</param>
|
||||
/// <param name="dependencies">FileDescriptors corresponding to all of the
|
||||
/// file's dependencies, in the exact order listed in the .proto file. May be null,
|
||||
/// in which case it is treated as an empty array.</param>
|
||||
/// <exception cref="DescriptorValidationException">If <paramref name="proto"/> is not
|
||||
/// a valid descriptor. This can occur for a number of reasons, such as a field
|
||||
/// having an undefined type or because two messages were defined with the same name.</exception>
|
||||
public static FileDescriptor BuildFrom(FileDescriptorProto proto, FileDescriptor[] dependencies)
|
||||
{
|
||||
return BuildFrom(proto, dependencies, false);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Builds a FileDescriptor from its protocol buffer representation.
|
||||
/// </summary>
|
||||
|
@ -33,23 +33,12 @@
|
||||
namespace Google.Protobuf.Descriptors
|
||||
{
|
||||
/// <summary>
|
||||
/// The non-generic form of the IDescriptor interface. Useful for describing a general
|
||||
/// descriptor.
|
||||
/// Interface implemented by all descriptor types.
|
||||
/// </summary>
|
||||
public interface IDescriptor
|
||||
{
|
||||
string Name { get; }
|
||||
string FullName { get; }
|
||||
FileDescriptor File { get; }
|
||||
IMessage Proto { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Strongly-typed form of the IDescriptor interface.
|
||||
/// </summary>
|
||||
/// <typeparam name="TProto">Protocol buffer type underlying this descriptor type</typeparam>
|
||||
internal interface IDescriptor<TProto> : IDescriptor where TProto : IMessage
|
||||
{
|
||||
new TProto Proto { get; }
|
||||
}
|
||||
}
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
#region Copyright notice and license
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#endregion
|
||||
|
||||
using Google.Protobuf.DescriptorProtos;
|
||||
|
||||
namespace Google.Protobuf.Descriptors
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for descriptors which are also indexed. This is all of them other than
|
||||
/// <see cref="FileDescriptor" />.
|
||||
/// </summary>
|
||||
public abstract class IndexedDescriptorBase<TProto, TOptions> : DescriptorBase<TProto, TOptions>
|
||||
where TProto : IMessage<TProto>, IDescriptorProto<TOptions>
|
||||
{
|
||||
private readonly int index;
|
||||
|
||||
protected IndexedDescriptorBase(TProto proto, FileDescriptor file, string fullName, int index)
|
||||
: base(proto, file, fullName)
|
||||
{
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
/// <value>
|
||||
/// The index of this descriptor within its parent descriptor.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// This returns the index of this descriptor within its parent, for
|
||||
/// this descriptor's type. (There can be duplicate values for different
|
||||
/// types, e.g. one enum type with index 0 and one message type with index 0.)
|
||||
/// </remarks>
|
||||
public int Index
|
||||
{
|
||||
get { return index; }
|
||||
}
|
||||
}
|
||||
}
|
@ -39,8 +39,9 @@ namespace Google.Protobuf.Descriptors
|
||||
/// <summary>
|
||||
/// Describes a message type.
|
||||
/// </summary>
|
||||
public sealed class MessageDescriptor : IndexedDescriptorBase<DescriptorProto, MessageOptions>
|
||||
public sealed class MessageDescriptor : DescriptorBase
|
||||
{
|
||||
private readonly DescriptorProto proto;
|
||||
private readonly MessageDescriptor containingType;
|
||||
private readonly IList<MessageDescriptor> nestedTypes;
|
||||
private readonly IList<EnumDescriptor> enumTypes;
|
||||
@ -48,8 +49,9 @@ namespace Google.Protobuf.Descriptors
|
||||
private readonly IList<OneofDescriptor> oneofs;
|
||||
|
||||
internal MessageDescriptor(DescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int typeIndex)
|
||||
: base(proto, file, ComputeFullName(file, parent, proto.Name), typeIndex)
|
||||
: base(file, file.ComputeFullName(parent, proto.Name), typeIndex)
|
||||
{
|
||||
this.proto = proto;
|
||||
containingType = parent;
|
||||
|
||||
oneofs = DescriptorUtil.ConvertAndMakeReadOnly(proto.OneofDecl,
|
||||
@ -68,23 +70,16 @@ namespace Google.Protobuf.Descriptors
|
||||
fields = DescriptorUtil.ConvertAndMakeReadOnly(proto.Field,
|
||||
(field, index) =>
|
||||
new FieldDescriptor(field, file, this, index));
|
||||
|
||||
for (int i = 0; i < proto.OneofDecl.Count; i++)
|
||||
{
|
||||
oneofs[i].fields = new FieldDescriptor[oneofs[i].FieldCount];
|
||||
oneofs[i].fieldCount = 0;
|
||||
}
|
||||
for (int i = 0; i< proto.Field.Count; i++)
|
||||
{
|
||||
OneofDescriptor oneofDescriptor = fields[i].ContainingOneof;
|
||||
if (oneofDescriptor != null)
|
||||
{
|
||||
oneofDescriptor.fields[oneofDescriptor.fieldCount++] = fields[i];
|
||||
}
|
||||
}
|
||||
file.DescriptorPool.AddSymbol(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The brief name of the descriptor's target.
|
||||
/// </summary>
|
||||
public override string Name { get { return proto.Name; } }
|
||||
|
||||
internal DescriptorProto Proto { get { return proto; } }
|
||||
|
||||
/// <value>
|
||||
/// If this is a nested type, get the outer descriptor, otherwise null.
|
||||
/// </value>
|
||||
@ -144,7 +139,7 @@ namespace Google.Protobuf.Descriptors
|
||||
|
||||
/// <summary>
|
||||
/// Finds a nested descriptor by name. The is valid for fields, nested
|
||||
/// message types and enums.
|
||||
/// message types, oneofs and enums.
|
||||
/// </summary>
|
||||
/// <param name="name">The unqualified name of the descriptor, e.g. "Foo"</param>
|
||||
/// <returns>The descriptor, or null if not found.</returns>
|
||||
@ -171,32 +166,8 @@ namespace Google.Protobuf.Descriptors
|
||||
|
||||
foreach (OneofDescriptor oneof in oneofs)
|
||||
{
|
||||
// TODO(jonskeet): Do we need to do this?
|
||||
// oneof.C
|
||||
oneof.CrossLink();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// See FileDescriptor.ReplaceProto
|
||||
/// </summary>
|
||||
internal override void ReplaceProto(DescriptorProto newProto)
|
||||
{
|
||||
base.ReplaceProto(newProto);
|
||||
|
||||
for (int i = 0; i < nestedTypes.Count; i++)
|
||||
{
|
||||
nestedTypes[i].ReplaceProto(newProto.NestedType[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < enumTypes.Count; i++)
|
||||
{
|
||||
enumTypes[i].ReplaceProto(newProto.EnumType[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < fields.Count; i++)
|
||||
{
|
||||
fields[i].ReplaceProto(newProto.Field[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -37,8 +37,9 @@ namespace Google.Protobuf.Descriptors
|
||||
/// <summary>
|
||||
/// Describes a single method in a service.
|
||||
/// </summary>
|
||||
public sealed class MethodDescriptor : IndexedDescriptorBase<MethodDescriptorProto, MethodOptions>
|
||||
public sealed class MethodDescriptor : DescriptorBase
|
||||
{
|
||||
private readonly MethodDescriptorProto proto;
|
||||
private readonly ServiceDescriptor service;
|
||||
private MessageDescriptor inputType;
|
||||
private MessageDescriptor outputType;
|
||||
@ -46,35 +47,34 @@ namespace Google.Protobuf.Descriptors
|
||||
/// <value>
|
||||
/// The service this method belongs to.
|
||||
/// </value>
|
||||
public ServiceDescriptor Service
|
||||
{
|
||||
get { return service; }
|
||||
}
|
||||
public ServiceDescriptor Service { get { return service; } }
|
||||
|
||||
/// <value>
|
||||
/// The method's input type.
|
||||
/// </value>
|
||||
public MessageDescriptor InputType
|
||||
{
|
||||
get { return inputType; }
|
||||
}
|
||||
public MessageDescriptor InputType { get { return inputType; } }
|
||||
|
||||
/// <value>
|
||||
/// The method's input type.
|
||||
/// </value>
|
||||
public MessageDescriptor OutputType
|
||||
{
|
||||
get { return outputType; }
|
||||
}
|
||||
public MessageDescriptor OutputType { get { return outputType; } }
|
||||
|
||||
internal MethodDescriptor(MethodDescriptorProto proto, FileDescriptor file,
|
||||
ServiceDescriptor parent, int index)
|
||||
: base(proto, file, parent.FullName + "." + proto.Name, index)
|
||||
: base(file, parent.FullName + "." + proto.Name, index)
|
||||
{
|
||||
this.proto = proto;
|
||||
service = parent;
|
||||
file.DescriptorPool.AddSymbol(this);
|
||||
}
|
||||
|
||||
internal MethodDescriptorProto Proto { get { return proto; } }
|
||||
|
||||
/// <summary>
|
||||
/// The brief name of the descriptor's target.
|
||||
/// </summary>
|
||||
public override string Name { get { return proto.Name; } }
|
||||
|
||||
internal void CrossLink()
|
||||
{
|
||||
IDescriptor lookup = File.DescriptorPool.LookupSymbol(Proto.InputType, this);
|
||||
|
@ -31,48 +31,49 @@
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using Google.Protobuf.DescriptorProtos;
|
||||
|
||||
namespace Google.Protobuf.Descriptors
|
||||
{
|
||||
public sealed class OneofDescriptor
|
||||
public sealed class OneofDescriptor : DescriptorBase
|
||||
{
|
||||
private int index;
|
||||
private OneofDescriptorProto proto;
|
||||
private FileDescriptor file;
|
||||
private readonly OneofDescriptorProto proto;
|
||||
private MessageDescriptor containingType;
|
||||
internal int fieldCount;
|
||||
internal 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)
|
||||
{
|
||||
this.proto = proto;
|
||||
this.file = file;
|
||||
this.index = index;
|
||||
|
||||
containingType = parent;
|
||||
fieldCount = 0;
|
||||
|
||||
file.DescriptorPool.AddSymbol(this);
|
||||
}
|
||||
|
||||
public int Index
|
||||
{
|
||||
get { return index; }
|
||||
}
|
||||
/// <summary>
|
||||
/// The brief name of the descriptor's target.
|
||||
/// </summary>
|
||||
public override string Name { get { return proto.Name; } }
|
||||
|
||||
public MessageDescriptor ContainingType
|
||||
{
|
||||
get { return containingType; }
|
||||
}
|
||||
|
||||
public int FieldCount
|
||||
{
|
||||
get { return fieldCount; }
|
||||
}
|
||||
public IList<FieldDescriptor> Fields { get { return fields; } }
|
||||
|
||||
public FieldDescriptor Field(int index)
|
||||
internal void CrossLink()
|
||||
{
|
||||
return fields[index];
|
||||
List<FieldDescriptor> fieldCollection = new List<FieldDescriptor>();
|
||||
foreach (var field in ContainingType.Fields)
|
||||
{
|
||||
if (field.ContainingOneof == this)
|
||||
{
|
||||
fieldCollection.Add(field);
|
||||
}
|
||||
}
|
||||
fields = new ReadOnlyCollection<FieldDescriptor>(fieldCollection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ namespace Google.Protobuf.Descriptors
|
||||
/// just as placeholders so that someone cannot define, say, a message type
|
||||
/// that has the same name as an existing package.
|
||||
/// </summary>
|
||||
internal sealed class PackageDescriptor : IDescriptor<IMessage>
|
||||
internal sealed class PackageDescriptor : IDescriptor
|
||||
{
|
||||
private readonly string name;
|
||||
private readonly string fullName;
|
||||
@ -50,11 +50,6 @@ namespace Google.Protobuf.Descriptors
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public IMessage Proto
|
||||
{
|
||||
get { return file.Proto; }
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return name; }
|
||||
|
@ -39,19 +39,28 @@ namespace Google.Protobuf.Descriptors
|
||||
/// <summary>
|
||||
/// Describes a service type.
|
||||
/// </summary>
|
||||
public sealed class ServiceDescriptor : IndexedDescriptorBase<ServiceDescriptorProto, ServiceOptions>
|
||||
public sealed class ServiceDescriptor : DescriptorBase
|
||||
{
|
||||
private readonly ServiceDescriptorProto proto;
|
||||
private readonly IList<MethodDescriptor> methods;
|
||||
|
||||
public ServiceDescriptor(ServiceDescriptorProto proto, FileDescriptor file, int index)
|
||||
: base(proto, file, ComputeFullName(file, null, proto.Name), index)
|
||||
internal ServiceDescriptor(ServiceDescriptorProto proto, FileDescriptor file, int index)
|
||||
: base(file, file.ComputeFullName(null, proto.Name), index)
|
||||
{
|
||||
this.proto = proto;
|
||||
methods = DescriptorUtil.ConvertAndMakeReadOnly(proto.Method,
|
||||
(method, i) => new MethodDescriptor(method, file, this, i));
|
||||
|
||||
file.DescriptorPool.AddSymbol(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The brief name of the descriptor's target.
|
||||
/// </summary>
|
||||
public override string Name { get { return proto.Name; } }
|
||||
|
||||
internal ServiceDescriptorProto Proto { get { return proto; } }
|
||||
|
||||
/// <value>
|
||||
/// An unmodifiable list of methods in this service.
|
||||
/// </value>
|
||||
@ -77,14 +86,5 @@ namespace Google.Protobuf.Descriptors
|
||||
method.CrossLink();
|
||||
}
|
||||
}
|
||||
|
||||
internal override void ReplaceProto(ServiceDescriptorProto newProto)
|
||||
{
|
||||
base.ReplaceProto(newProto);
|
||||
for (int i = 0; i < methods.Count; i++)
|
||||
{
|
||||
methods[i].ReplaceProto(newProto.Method[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -61,7 +61,6 @@
|
||||
<Compile Include="Collections\ReadOnlyDictionary.cs" />
|
||||
<Compile Include="Collections\RepeatedField.cs" />
|
||||
<Compile Include="DescriptorProtos\DescriptorProtoFile.cs" />
|
||||
<Compile Include="DescriptorProtos\IDescriptorProto.cs" />
|
||||
<Compile Include="DescriptorProtos\PartialClasses.cs" />
|
||||
<Compile Include="Descriptors\DescriptorBase.cs" />
|
||||
<Compile Include="Descriptors\DescriptorPool.cs" />
|
||||
@ -74,7 +73,6 @@
|
||||
<Compile Include="Descriptors\FileDescriptor.cs" />
|
||||
<Compile Include="Descriptors\OneofDescriptor.cs" />
|
||||
<Compile Include="Descriptors\IDescriptor.cs" />
|
||||
<Compile Include="Descriptors\IndexedDescriptorBase.cs" />
|
||||
<Compile Include="Descriptors\MessageDescriptor.cs" />
|
||||
<Compile Include="Descriptors\MethodDescriptor.cs" />
|
||||
<Compile Include="Descriptors\PackageDescriptor.cs" />
|
||||
|
Loading…
Reference in New Issue
Block a user