xref: /aosp_15_r20/external/protobuf/csharp/src/Google.Protobuf/ExtensionRegistry.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;
34*1b3f573fSAndroid Build Coastguard Worker using System.Collections;
35*1b3f573fSAndroid Build Coastguard Worker using System.Collections.Generic;
36*1b3f573fSAndroid Build Coastguard Worker using System.Linq;
37*1b3f573fSAndroid Build Coastguard Worker 
38*1b3f573fSAndroid Build Coastguard Worker namespace Google.Protobuf
39*1b3f573fSAndroid Build Coastguard Worker {
40*1b3f573fSAndroid Build Coastguard Worker     /// <summary>
41*1b3f573fSAndroid Build Coastguard Worker     /// Provides extensions to messages while parsing. This API is experimental and subject to change.
42*1b3f573fSAndroid Build Coastguard Worker     /// </summary>
43*1b3f573fSAndroid Build Coastguard Worker     public sealed class ExtensionRegistry : ICollection<Extension>, IDeepCloneable<ExtensionRegistry>
44*1b3f573fSAndroid Build Coastguard Worker     {
45*1b3f573fSAndroid Build Coastguard Worker         internal sealed class ExtensionComparer : IEqualityComparer<Extension>
46*1b3f573fSAndroid Build Coastguard Worker         {
Equals(Extension a, Extension b)47*1b3f573fSAndroid Build Coastguard Worker             public bool Equals(Extension a, Extension b)
48*1b3f573fSAndroid Build Coastguard Worker             {
49*1b3f573fSAndroid Build Coastguard Worker                 return new ObjectIntPair<Type>(a.TargetType, a.FieldNumber).Equals(new ObjectIntPair<Type>(b.TargetType, b.FieldNumber));
50*1b3f573fSAndroid Build Coastguard Worker             }
GetHashCode(Extension a)51*1b3f573fSAndroid Build Coastguard Worker             public int GetHashCode(Extension a)
52*1b3f573fSAndroid Build Coastguard Worker             {
53*1b3f573fSAndroid Build Coastguard Worker                 return new ObjectIntPair<Type>(a.TargetType, a.FieldNumber).GetHashCode();
54*1b3f573fSAndroid Build Coastguard Worker             }
55*1b3f573fSAndroid Build Coastguard Worker 
56*1b3f573fSAndroid Build Coastguard Worker             internal static ExtensionComparer Instance = new ExtensionComparer();
57*1b3f573fSAndroid Build Coastguard Worker         }
58*1b3f573fSAndroid Build Coastguard Worker         private IDictionary<ObjectIntPair<Type>, Extension> extensions;
59*1b3f573fSAndroid Build Coastguard Worker 
60*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
61*1b3f573fSAndroid Build Coastguard Worker         /// Creates a new empty extension registry
62*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
ExtensionRegistry()63*1b3f573fSAndroid Build Coastguard Worker         public ExtensionRegistry()
64*1b3f573fSAndroid Build Coastguard Worker         {
65*1b3f573fSAndroid Build Coastguard Worker             extensions = new Dictionary<ObjectIntPair<Type>, Extension>();
66*1b3f573fSAndroid Build Coastguard Worker         }
67*1b3f573fSAndroid Build Coastguard Worker 
ExtensionRegistry(IDictionary<ObjectIntPair<Type>, Extension> collection)68*1b3f573fSAndroid Build Coastguard Worker         private ExtensionRegistry(IDictionary<ObjectIntPair<Type>, Extension> collection)
69*1b3f573fSAndroid Build Coastguard Worker         {
70*1b3f573fSAndroid Build Coastguard Worker             extensions = collection.ToDictionary(k => k.Key, v => v.Value);
71*1b3f573fSAndroid Build Coastguard Worker         }
72*1b3f573fSAndroid Build Coastguard Worker 
73*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
74*1b3f573fSAndroid Build Coastguard Worker         /// Gets the total number of extensions in this extension registry
75*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
76*1b3f573fSAndroid Build Coastguard Worker         public int Count => extensions.Count;
77*1b3f573fSAndroid Build Coastguard Worker 
78*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
79*1b3f573fSAndroid Build Coastguard Worker         /// Returns whether the registry is readonly
80*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
81*1b3f573fSAndroid Build Coastguard Worker         bool ICollection<Extension>.IsReadOnly => false;
82*1b3f573fSAndroid Build Coastguard Worker 
ContainsInputField(uint lastTag, Type target, out Extension extension)83*1b3f573fSAndroid Build Coastguard Worker         internal bool ContainsInputField(uint lastTag, Type target, out Extension extension)
84*1b3f573fSAndroid Build Coastguard Worker         {
85*1b3f573fSAndroid Build Coastguard Worker             return extensions.TryGetValue(new ObjectIntPair<Type>(target, WireFormat.GetTagFieldNumber(lastTag)), out extension);
86*1b3f573fSAndroid Build Coastguard Worker         }
87*1b3f573fSAndroid Build Coastguard Worker 
88*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
89*1b3f573fSAndroid Build Coastguard Worker         /// Adds the specified extension to the registry
90*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
Add(Extension extension)91*1b3f573fSAndroid Build Coastguard Worker         public void Add(Extension extension)
92*1b3f573fSAndroid Build Coastguard Worker         {
93*1b3f573fSAndroid Build Coastguard Worker             ProtoPreconditions.CheckNotNull(extension, nameof(extension));
94*1b3f573fSAndroid Build Coastguard Worker 
95*1b3f573fSAndroid Build Coastguard Worker             extensions.Add(new ObjectIntPair<Type>(extension.TargetType, extension.FieldNumber), extension);
96*1b3f573fSAndroid Build Coastguard Worker         }
97*1b3f573fSAndroid Build Coastguard Worker 
98*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
99*1b3f573fSAndroid Build Coastguard Worker         /// Adds the specified extensions to the registry
100*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
AddRange(IEnumerable<Extension> extensions)101*1b3f573fSAndroid Build Coastguard Worker         public void AddRange(IEnumerable<Extension> extensions)
102*1b3f573fSAndroid Build Coastguard Worker         {
103*1b3f573fSAndroid Build Coastguard Worker             ProtoPreconditions.CheckNotNull(extensions, nameof(extensions));
104*1b3f573fSAndroid Build Coastguard Worker 
105*1b3f573fSAndroid Build Coastguard Worker             foreach (var extension in extensions)
106*1b3f573fSAndroid Build Coastguard Worker             {
107*1b3f573fSAndroid Build Coastguard Worker                 Add(extension);
108*1b3f573fSAndroid Build Coastguard Worker             }
109*1b3f573fSAndroid Build Coastguard Worker         }
110*1b3f573fSAndroid Build Coastguard Worker 
111*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
112*1b3f573fSAndroid Build Coastguard Worker         /// Clears the registry of all values
113*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
Clear()114*1b3f573fSAndroid Build Coastguard Worker         public void Clear()
115*1b3f573fSAndroid Build Coastguard Worker         {
116*1b3f573fSAndroid Build Coastguard Worker             extensions.Clear();
117*1b3f573fSAndroid Build Coastguard Worker         }
118*1b3f573fSAndroid Build Coastguard Worker 
119*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
120*1b3f573fSAndroid Build Coastguard Worker         /// Gets whether the extension registry contains the specified extension
121*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
Contains(Extension item)122*1b3f573fSAndroid Build Coastguard Worker         public bool Contains(Extension item)
123*1b3f573fSAndroid Build Coastguard Worker         {
124*1b3f573fSAndroid Build Coastguard Worker             ProtoPreconditions.CheckNotNull(item, nameof(item));
125*1b3f573fSAndroid Build Coastguard Worker 
126*1b3f573fSAndroid Build Coastguard Worker             return extensions.ContainsKey(new ObjectIntPair<Type>(item.TargetType, item.FieldNumber));
127*1b3f573fSAndroid Build Coastguard Worker         }
128*1b3f573fSAndroid Build Coastguard Worker 
129*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
130*1b3f573fSAndroid Build Coastguard Worker         /// Copies the arrays in the registry set to the specified array at the specified index
131*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
132*1b3f573fSAndroid Build Coastguard Worker         /// <param name="array">The array to copy to</param>
133*1b3f573fSAndroid Build Coastguard Worker         /// <param name="arrayIndex">The array index to start at</param>
CopyTo(Extension[] array, int arrayIndex)134*1b3f573fSAndroid Build Coastguard Worker         void ICollection<Extension>.CopyTo(Extension[] array, int arrayIndex)
135*1b3f573fSAndroid Build Coastguard Worker         {
136*1b3f573fSAndroid Build Coastguard Worker             ProtoPreconditions.CheckNotNull(array, nameof(array));
137*1b3f573fSAndroid Build Coastguard Worker             if (arrayIndex < 0 || arrayIndex >= array.Length)
138*1b3f573fSAndroid Build Coastguard Worker             {
139*1b3f573fSAndroid Build Coastguard Worker                 throw new ArgumentOutOfRangeException(nameof(arrayIndex));
140*1b3f573fSAndroid Build Coastguard Worker             }
141*1b3f573fSAndroid Build Coastguard Worker             if (array.Length - arrayIndex < Count)
142*1b3f573fSAndroid Build Coastguard Worker             {
143*1b3f573fSAndroid Build Coastguard Worker                 throw new ArgumentException("The provided array is shorter than the number of elements in the registry");
144*1b3f573fSAndroid Build Coastguard Worker             }
145*1b3f573fSAndroid Build Coastguard Worker 
146*1b3f573fSAndroid Build Coastguard Worker             for (int i = 0; i < array.Length; i++)
147*1b3f573fSAndroid Build Coastguard Worker             {
148*1b3f573fSAndroid Build Coastguard Worker                 Extension extension = array[i];
149*1b3f573fSAndroid Build Coastguard Worker                 extensions.Add(new ObjectIntPair<Type>(extension.TargetType, extension.FieldNumber), extension);
150*1b3f573fSAndroid Build Coastguard Worker             }
151*1b3f573fSAndroid Build Coastguard Worker         }
152*1b3f573fSAndroid Build Coastguard Worker 
153*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
154*1b3f573fSAndroid Build Coastguard Worker         /// Returns an enumerator to enumerate through the items in the registry
155*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
156*1b3f573fSAndroid Build Coastguard Worker         /// <returns>Returns an enumerator for the extensions in this registry</returns>
GetEnumerator()157*1b3f573fSAndroid Build Coastguard Worker         public IEnumerator<Extension> GetEnumerator()
158*1b3f573fSAndroid Build Coastguard Worker         {
159*1b3f573fSAndroid Build Coastguard Worker             return extensions.Values.GetEnumerator();
160*1b3f573fSAndroid Build Coastguard Worker         }
161*1b3f573fSAndroid Build Coastguard Worker 
162*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
163*1b3f573fSAndroid Build Coastguard Worker         /// Removes the specified extension from the set
164*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
165*1b3f573fSAndroid Build Coastguard Worker         /// <param name="item">The extension</param>
166*1b3f573fSAndroid Build Coastguard Worker         /// <returns><c>true</c> if the extension was removed, otherwise <c>false</c></returns>
Remove(Extension item)167*1b3f573fSAndroid Build Coastguard Worker         public bool Remove(Extension item)
168*1b3f573fSAndroid Build Coastguard Worker         {
169*1b3f573fSAndroid Build Coastguard Worker             ProtoPreconditions.CheckNotNull(item, nameof(item));
170*1b3f573fSAndroid Build Coastguard Worker 
171*1b3f573fSAndroid Build Coastguard Worker             return extensions.Remove(new ObjectIntPair<Type>(item.TargetType, item.FieldNumber));
172*1b3f573fSAndroid Build Coastguard Worker         }
173*1b3f573fSAndroid Build Coastguard Worker 
IEnumerable.GetEnumerator()174*1b3f573fSAndroid Build Coastguard Worker         IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
175*1b3f573fSAndroid Build Coastguard Worker 
176*1b3f573fSAndroid Build Coastguard Worker         /// <summary>
177*1b3f573fSAndroid Build Coastguard Worker         /// Clones the registry into a new registry
178*1b3f573fSAndroid Build Coastguard Worker         /// </summary>
Clone()179*1b3f573fSAndroid Build Coastguard Worker         public ExtensionRegistry Clone()
180*1b3f573fSAndroid Build Coastguard Worker         {
181*1b3f573fSAndroid Build Coastguard Worker             return new ExtensionRegistry(extensions);
182*1b3f573fSAndroid Build Coastguard Worker         }
183*1b3f573fSAndroid Build Coastguard Worker     }
184*1b3f573fSAndroid Build Coastguard Worker }
185