Add an extension registry option when parsing file descriptors

This is important when parsing descriptor sets that contain extensions.
(The alternative is to get the descriptor bytes again for individual
elements, e.g. message descriptors, and reparse them with the
appropriate extensions. It's really ugly.)
This commit is contained in:
Jon Skeet 2021-01-20 08:11:27 +00:00
parent cea3653a2e
commit f01d9e5601
2 changed files with 37 additions and 2 deletions

View File

@ -35,7 +35,9 @@ using NUnit.Framework;
using ProtobufUnittest;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnitTest.Issues.TestProtos;
namespace Google.Protobuf.Reflection
{
@ -70,6 +72,24 @@ namespace Google.Protobuf.Reflection
TestFileDescriptor(converted[2], converted[1], converted[0]);
}
[Test]
public void FileDescriptor_BuildFromByteStrings_WithExtensionRegistry()
{
var extension = UnittestCustomOptionsProto3Extensions.MessageOpt1;
var byteStrings = new[]
{
DescriptorReflection.Descriptor.Proto.ToByteString(),
UnittestCustomOptionsProto3Reflection.Descriptor.Proto.ToByteString()
};
var registry = new ExtensionRegistry { extension };
var descriptor = FileDescriptor.BuildFromByteStrings(byteStrings, registry).Last();
var message = descriptor.MessageTypes.Single(t => t.Name == nameof(TestMessageWithCustomOptions));
var extensionValue = message.GetOptions().GetExtension(extension);
Assert.AreEqual(-56, extensionValue);
}
private void TestFileDescriptor(FileDescriptor file, FileDescriptor importedFile, FileDescriptor importedPublicFile)
{
Assert.AreEqual("unittest_proto3.proto", file.Name);

View File

@ -481,18 +481,21 @@ namespace Google.Protobuf.Reflection
/// dependencies must come before the descriptor which depends on them. (If A depends on B, and B
/// depends on C, then the descriptors must be presented in the order C, B, A.) This is compatible
/// with the order in which protoc provides descriptors to plugins.</param>
/// <param name="registry">The extension registry to use when parsing, or null if no extensions are required.</param>
/// <returns>The file descriptors corresponding to <paramref name="descriptorData"/>.</returns>
public static IReadOnlyList<FileDescriptor> BuildFromByteStrings(IEnumerable<ByteString> descriptorData)
public static IReadOnlyList<FileDescriptor> BuildFromByteStrings(IEnumerable<ByteString> descriptorData, ExtensionRegistry registry)
{
ProtoPreconditions.CheckNotNull(descriptorData, nameof(descriptorData));
var parser = FileDescriptorProto.Parser.WithExtensionRegistry(registry);
// TODO: See if we can build a single DescriptorPool instead of building lots of them.
// This will all behave correctly, but it's less efficient than we'd like.
var descriptors = new List<FileDescriptor>();
var descriptorsByName = new Dictionary<string, FileDescriptor>();
foreach (var data in descriptorData)
{
var proto = FileDescriptorProto.Parser.ParseFrom(data);
var proto = parser.ParseFrom(data);
var dependencies = new List<FileDescriptor>();
foreach (var dependencyName in proto.Dependency)
{
@ -518,6 +521,18 @@ namespace Google.Protobuf.Reflection
return new ReadOnlyCollection<FileDescriptor>(descriptors);
}
/// <summary>
/// Converts the given descriptor binary data into FileDescriptor objects.
/// Note: reflection using the returned FileDescriptors is not currently supported.
/// </summary>
/// <param name="descriptorData">The binary file descriptor proto data. Must not be null, and any
/// dependencies must come before the descriptor which depends on them. (If A depends on B, and B
/// depends on C, then the descriptors must be presented in the order C, B, A.) This is compatible
/// with the order in which protoc provides descriptors to plugins.</param>
/// <returns>The file descriptors corresponding to <paramref name="descriptorData"/>.</returns>
public static IReadOnlyList<FileDescriptor> BuildFromByteStrings(IEnumerable<ByteString> descriptorData) =>
BuildFromByteStrings(descriptorData, null);
/// <summary>
/// Returns a <see cref="System.String" /> that represents this instance.
/// </summary>