#region Copyright notice and license
#endregion
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
namespace Google.Protobuf.Reflection
{
[DebuggerDisplay("Count = {UnorderedExtensions.Count}")]
[DebuggerTypeProxy(typeof(ExtensionCollectionDebugView))]
public sealed class ExtensionCollection
{
private IDictionary<MessageDescriptor, IList<FieldDescriptor>> extensionsByTypeInDeclarationOrder;
private IDictionary<MessageDescriptor, IList<FieldDescriptor>> extensionsByTypeInNumberOrder;
internal ExtensionCollection(FileDescriptor file, Extension[] extensions)
{
UnorderedExtensions = DescriptorUtil.ConvertAndMakeReadOnly(
file.Proto.Extension,
(extension, i) => {
if (extensions?.Length != 0)
{
return new FieldDescriptor(extension, file, null, i, null, extensions?[i]);
}
else
{
return new FieldDescriptor(extension, file, null, i, null, null); }
});
}
internal ExtensionCollection(MessageDescriptor message, Extension[] extensions)
{
UnorderedExtensions = DescriptorUtil.ConvertAndMakeReadOnly(
message.Proto.Extension,
(extension, i) => {
if (extensions?.Length != 0)
{
return new FieldDescriptor(extension, message.File, message, i, null, extensions?[i]);
}
else
{
return new FieldDescriptor(extension, message.File, message, i, null, null);
}
});
}
public IList<FieldDescriptor> UnorderedExtensions { get; }
public IList<FieldDescriptor> GetExtensionsInDeclarationOrder(MessageDescriptor descriptor)
{
return extensionsByTypeInDeclarationOrder[descriptor];
}
public IList<FieldDescriptor> GetExtensionsInNumberOrder(MessageDescriptor descriptor)
{
return extensionsByTypeInNumberOrder[descriptor];
}
internal void CrossLink()
{
Dictionary<MessageDescriptor, IList<FieldDescriptor>> declarationOrder = new Dictionary<MessageDescriptor, IList<FieldDescriptor>>();
foreach (FieldDescriptor descriptor in UnorderedExtensions)
{
descriptor.CrossLink();
if (!declarationOrder.TryGetValue(descriptor.ExtendeeType, out IList<FieldDescriptor> list))
{
list = new List<FieldDescriptor>();
declarationOrder.Add(descriptor.ExtendeeType, list);
}
list.Add(descriptor);
}
extensionsByTypeInDeclarationOrder = declarationOrder
.ToDictionary(kvp => kvp.Key, kvp => (IList<FieldDescriptor>)new ReadOnlyCollection<FieldDescriptor>(kvp.Value));
extensionsByTypeInNumberOrder = declarationOrder
.ToDictionary(kvp => kvp.Key, kvp => (IList<FieldDescriptor>)new ReadOnlyCollection<FieldDescriptor>(kvp.Value.OrderBy(field => field.FieldNumber).ToArray()));
}
private sealed class ExtensionCollectionDebugView
{
private readonly ExtensionCollection list;
public ExtensionCollectionDebugView(ExtensionCollection list)
{
this.list = list;
}
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public FieldDescriptor[] Items => list.UnorderedExtensions.ToArray();
}
}
}