xref: /aosp_15_r20/external/protobuf/csharp/src/Google.Protobuf/Reflection/ExtensionCollection.cs (revision 1b3f573f81763fcece89efc2b6a5209149e44ab8)
1*1b3f573fSAndroid Build Coastguard Worker #region Copyright notice and license
2*1b3f573fSAndroid Build Coastguard Worker // Protocol Buffers - Google's data interchange format
3*1b3f573fSAndroid Build Coastguard Worker // Copyright 2008 Google Inc.  All rights reserved.
4*1b3f573fSAndroid Build Coastguard Worker // https://developers.google.com/protocol-buffers/
5*1b3f573fSAndroid Build Coastguard Worker //
6*1b3f573fSAndroid Build Coastguard Worker // Redistribution and use in source and binary forms, with or without
7*1b3f573fSAndroid Build Coastguard Worker // modification, are permitted provided that the following conditions are
8*1b3f573fSAndroid Build Coastguard Worker // met:
9*1b3f573fSAndroid Build Coastguard Worker //
10*1b3f573fSAndroid Build Coastguard Worker //     * Redistributions of source code must retain the above copyright
11*1b3f573fSAndroid Build Coastguard Worker // notice, this list of conditions and the following disclaimer.
12*1b3f573fSAndroid Build Coastguard Worker //     * Redistributions in binary form must reproduce the above
13*1b3f573fSAndroid Build Coastguard Worker // copyright notice, this list of conditions and the following disclaimer
14*1b3f573fSAndroid Build Coastguard Worker // in the documentation and/or other materials provided with the
15*1b3f573fSAndroid Build Coastguard Worker // distribution.
16*1b3f573fSAndroid Build Coastguard Worker //     * Neither the name of Google Inc. nor the names of its
17*1b3f573fSAndroid Build Coastguard Worker // contributors may be used to endorse or promote products derived from
18*1b3f573fSAndroid Build Coastguard Worker // this software without specific prior written permission.
19*1b3f573fSAndroid Build Coastguard Worker //
20*1b3f573fSAndroid Build Coastguard Worker // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21*1b3f573fSAndroid Build Coastguard Worker // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22*1b3f573fSAndroid Build Coastguard Worker // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23*1b3f573fSAndroid Build Coastguard Worker // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24*1b3f573fSAndroid Build Coastguard Worker // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25*1b3f573fSAndroid Build Coastguard Worker // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26*1b3f573fSAndroid Build Coastguard Worker // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27*1b3f573fSAndroid Build Coastguard Worker // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28*1b3f573fSAndroid Build Coastguard Worker // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29*1b3f573fSAndroid Build Coastguard Worker // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30*1b3f573fSAndroid Build Coastguard Worker // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31*1b3f573fSAndroid Build Coastguard Worker #endregion
32*1b3f573fSAndroid Build Coastguard Worker 
33*1b3f573fSAndroid Build Coastguard Worker using System.Collections.Generic;
34*1b3f573fSAndroid Build Coastguard Worker using System.Collections.ObjectModel;
35*1b3f573fSAndroid Build Coastguard Worker using System.Linq;
36*1b3f573fSAndroid Build Coastguard Worker 
37*1b3f573fSAndroid Build Coastguard Worker namespace Google.Protobuf.Reflection
38*1b3f573fSAndroid Build Coastguard Worker {
39*1b3f573fSAndroid Build Coastguard Worker     /// <summary>
40*1b3f573fSAndroid Build Coastguard Worker     /// A collection to simplify retrieving the descriptors of extensions in a descriptor for a message
41*1b3f573fSAndroid Build Coastguard Worker     /// </summary>
42*1b3f573fSAndroid Build Coastguard Worker     public sealed class ExtensionCollection
43*1b3f573fSAndroid Build Coastguard Worker     {
44*1b3f573fSAndroid Build Coastguard Worker         private IDictionary<MessageDescriptor, IList<FieldDescriptor>> extensionsByTypeInDeclarationOrder;
45*1b3f573fSAndroid Build Coastguard Worker         private IDictionary<MessageDescriptor, IList<FieldDescriptor>> extensionsByTypeInNumberOrder;
46*1b3f573fSAndroid Build Coastguard Worker 
ExtensionCollection(FileDescriptor file, Extension[] extensions)47*1b3f573fSAndroid Build Coastguard Worker         internal ExtensionCollection(FileDescriptor file, Extension[] extensions)
48*1b3f573fSAndroid Build Coastguard Worker         {
49*1b3f573fSAndroid Build Coastguard Worker             UnorderedExtensions = DescriptorUtil.ConvertAndMakeReadOnly(
50*1b3f573fSAndroid Build Coastguard Worker                 file.Proto.Extension,
51*1b3f573fSAndroid Build Coastguard Worker                 (extension, i) => {
52*1b3f573fSAndroid Build Coastguard Worker                     if (extensions?.Length != 0)
53*1b3f573fSAndroid Build Coastguard Worker                     {
54*1b3f573fSAndroid Build Coastguard Worker                         return new FieldDescriptor(extension, file, null, i, null, extensions?[i]);
55*1b3f573fSAndroid Build Coastguard Worker                     }
56*1b3f573fSAndroid Build Coastguard Worker                     else
57*1b3f573fSAndroid Build Coastguard Worker                     {
58*1b3f573fSAndroid Build Coastguard Worker                         return new FieldDescriptor(extension, file, null, i, null, null); // return null if there's no extensions in this array for old code-gen
59*1b3f573fSAndroid Build Coastguard Worker                     }
60*1b3f573fSAndroid Build Coastguard Worker                 });
61*1b3f573fSAndroid Build Coastguard Worker         }
62*1b3f573fSAndroid Build Coastguard Worker 
ExtensionCollection(MessageDescriptor message, Extension[] extensions)63*1b3f573fSAndroid Build Coastguard Worker         internal ExtensionCollection(MessageDescriptor message, Extension[] extensions)
64*1b3f573fSAndroid Build Coastguard Worker         {
65*1b3f573fSAndroid Build Coastguard Worker             UnorderedExtensions = DescriptorUtil.ConvertAndMakeReadOnly(
66*1b3f573fSAndroid Build Coastguard Worker                 message.Proto.Extension,
67*1b3f573fSAndroid Build Coastguard Worker                 (extension, i) => {
68*1b3f573fSAndroid Build Coastguard Worker                     if (extensions?.Length != 0)
69*1b3f573fSAndroid Build Coastguard Worker                     {
70*1b3f573fSAndroid Build Coastguard Worker                         return new FieldDescriptor(extension, message.File, message, i, null, extensions?[i]);
71*1b3f573fSAndroid Build Coastguard Worker                     }
72*1b3f573fSAndroid Build Coastguard Worker                     else
73*1b3f573fSAndroid Build Coastguard Worker                     {
74*1b3f573fSAndroid Build Coastguard Worker                         return new FieldDescriptor(extension, message.File, message, i, null, null);
75*1b3f573fSAndroid Build Coastguard Worker                     }
76*1b3f573fSAndroid Build Coastguard Worker                 });
77*1b3f573fSAndroid Build Coastguard Worker         }
78*1b3f573fSAndroid Build Coastguard Worker 
79*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
80*1b3f573fSAndroid Build Coastguard Worker         /// Returns a readonly list of all the extensions defined in this type in
81*1b3f573fSAndroid Build Coastguard Worker         /// the order they were defined in the source .proto file
82*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
83*1b3f573fSAndroid Build Coastguard Worker         public IList<FieldDescriptor> UnorderedExtensions { get; }
84*1b3f573fSAndroid Build Coastguard Worker 
85*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
86*1b3f573fSAndroid Build Coastguard Worker         /// Returns a readonly list of all the extensions define in this type that extend
87*1b3f573fSAndroid Build Coastguard Worker         /// the provided descriptor type in the order they were defined in the source .proto file
88*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
GetExtensionsInDeclarationOrder(MessageDescriptor descriptor)89*1b3f573fSAndroid Build Coastguard Worker         public IList<FieldDescriptor> GetExtensionsInDeclarationOrder(MessageDescriptor descriptor)
90*1b3f573fSAndroid Build Coastguard Worker         {
91*1b3f573fSAndroid Build Coastguard Worker             return extensionsByTypeInDeclarationOrder[descriptor];
92*1b3f573fSAndroid Build Coastguard Worker         }
93*1b3f573fSAndroid Build Coastguard Worker 
94*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
95*1b3f573fSAndroid Build Coastguard Worker         /// Returns a readonly list of all the extensions define in this type that extend
96*1b3f573fSAndroid Build Coastguard Worker         /// the provided descriptor type in ascending field order
97*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
GetExtensionsInNumberOrder(MessageDescriptor descriptor)98*1b3f573fSAndroid Build Coastguard Worker         public IList<FieldDescriptor> GetExtensionsInNumberOrder(MessageDescriptor descriptor)
99*1b3f573fSAndroid Build Coastguard Worker         {
100*1b3f573fSAndroid Build Coastguard Worker             return extensionsByTypeInNumberOrder[descriptor];
101*1b3f573fSAndroid Build Coastguard Worker         }
102*1b3f573fSAndroid Build Coastguard Worker 
CrossLink()103*1b3f573fSAndroid Build Coastguard Worker         internal void CrossLink()
104*1b3f573fSAndroid Build Coastguard Worker         {
105*1b3f573fSAndroid Build Coastguard Worker             Dictionary<MessageDescriptor, IList<FieldDescriptor>> declarationOrder = new Dictionary<MessageDescriptor, IList<FieldDescriptor>>();
106*1b3f573fSAndroid Build Coastguard Worker             foreach (FieldDescriptor descriptor in UnorderedExtensions)
107*1b3f573fSAndroid Build Coastguard Worker             {
108*1b3f573fSAndroid Build Coastguard Worker                 descriptor.CrossLink();
109*1b3f573fSAndroid Build Coastguard Worker 
110*1b3f573fSAndroid Build Coastguard Worker                 IList<FieldDescriptor> list;
111*1b3f573fSAndroid Build Coastguard Worker                 if (!declarationOrder.TryGetValue(descriptor.ExtendeeType, out list))
112*1b3f573fSAndroid Build Coastguard Worker                 {
113*1b3f573fSAndroid Build Coastguard Worker                     list = new List<FieldDescriptor>();
114*1b3f573fSAndroid Build Coastguard Worker                     declarationOrder.Add(descriptor.ExtendeeType, list);
115*1b3f573fSAndroid Build Coastguard Worker                 }
116*1b3f573fSAndroid Build Coastguard Worker 
117*1b3f573fSAndroid Build Coastguard Worker                 list.Add(descriptor);
118*1b3f573fSAndroid Build Coastguard Worker             }
119*1b3f573fSAndroid Build Coastguard Worker 
120*1b3f573fSAndroid Build Coastguard Worker             extensionsByTypeInDeclarationOrder = declarationOrder
121*1b3f573fSAndroid Build Coastguard Worker                 .ToDictionary(kvp => kvp.Key, kvp => (IList<FieldDescriptor>)new ReadOnlyCollection<FieldDescriptor>(kvp.Value));
122*1b3f573fSAndroid Build Coastguard Worker             extensionsByTypeInNumberOrder = declarationOrder
123*1b3f573fSAndroid Build Coastguard Worker                 .ToDictionary(kvp => kvp.Key, kvp => (IList<FieldDescriptor>)new ReadOnlyCollection<FieldDescriptor>(kvp.Value.OrderBy(field => field.FieldNumber).ToArray()));
124*1b3f573fSAndroid Build Coastguard Worker         }
125*1b3f573fSAndroid Build Coastguard Worker     }
126*1b3f573fSAndroid Build Coastguard Worker }
127