• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #region Copyright notice and license
2 // Protocol Buffers - Google's data interchange format
3 // Copyright 2008 Google Inc.  All rights reserved.
4 // https://developers.google.com/protocol-buffers/
5 //
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are
8 // met:
9 //
10 //     * Redistributions of source code must retain the above copyright
11 // notice, this list of conditions and the following disclaimer.
12 //     * Redistributions in binary form must reproduce the above
13 // copyright notice, this list of conditions and the following disclaimer
14 // in the documentation and/or other materials provided with the
15 // distribution.
16 //     * Neither the name of Google Inc. nor the names of its
17 // contributors may be used to endorse or promote products derived from
18 // this software without specific prior written permission.
19 //
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #endregion
32 
33 using System;
34 using System.Collections;
35 using System.Collections.Generic;
36 using System.Linq;
37 
38 namespace Google.Protobuf
39 {
40     /// <summary>
41     /// Provides extensions to messages while parsing. This API is experimental and subject to change.
42     /// </summary>
43     public sealed class ExtensionRegistry : ICollection<Extension>, IDeepCloneable<ExtensionRegistry>
44     {
45         private IDictionary<ObjectIntPair<Type>, Extension> extensions;
46 
47         /// <summary>
48         /// Creates a new empty extension registry
49         /// </summary>
ExtensionRegistry()50         public ExtensionRegistry()
51         {
52             extensions = new Dictionary<ObjectIntPair<Type>, Extension>();
53         }
54 
ExtensionRegistry(IDictionary<ObjectIntPair<Type>, Extension> collection)55         private ExtensionRegistry(IDictionary<ObjectIntPair<Type>, Extension> collection)
56         {
57             extensions = collection.ToDictionary(k => k.Key, v => v.Value);
58         }
59 
60         /// <summary>
61         /// Gets the total number of extensions in this extension registry
62         /// </summary>
63         public int Count => extensions.Count;
64 
65         /// <summary>
66         /// Returns whether the registry is readonly
67         /// </summary>
68         bool ICollection<Extension>.IsReadOnly => false;
69 
ContainsInputField(CodedInputStream stream, Type target, out Extension extension)70         internal bool ContainsInputField(CodedInputStream stream, Type target, out Extension extension)
71         {
72             return extensions.TryGetValue(new ObjectIntPair<Type>(target, WireFormat.GetTagFieldNumber(stream.LastTag)), out extension);
73         }
74 
75         /// <summary>
76         /// Adds the specified extension to the registry
77         /// </summary>
Add(Extension extension)78         public void Add(Extension extension)
79         {
80             ProtoPreconditions.CheckNotNull(extension, nameof(extension));
81 
82             extensions.Add(new ObjectIntPair<Type>(extension.TargetType, extension.FieldNumber), extension);
83         }
84 
85         /// <summary>
86         /// Adds the specified extensions to the reigstry
87         /// </summary>
AddRange(IEnumerable<Extension> extensions)88         public void AddRange(IEnumerable<Extension> extensions)
89         {
90             ProtoPreconditions.CheckNotNull(extensions, nameof(extensions));
91 
92             foreach (var extension in extensions)
93                 Add(extension);
94         }
95 
96         /// <summary>
97         /// Clears the registry of all values
98         /// </summary>
Clear()99         public void Clear()
100         {
101             extensions.Clear();
102         }
103 
104         /// <summary>
105         /// Gets whether the extension registry contains the specified extension
106         /// </summary>
Contains(Extension item)107         public bool Contains(Extension item)
108         {
109             ProtoPreconditions.CheckNotNull(item, nameof(item));
110 
111             return extensions.ContainsKey(new ObjectIntPair<Type>(item.TargetType, item.FieldNumber));
112         }
113 
114         /// <summary>
115         /// Copies the arrays in the registry set to the specified array at the specified index
116         /// </summary>
117         /// <param name="array">The array to copy to</param>
118         /// <param name="arrayIndex">The array index to start at</param>
CopyTo(Extension[] array, int arrayIndex)119         void ICollection<Extension>.CopyTo(Extension[] array, int arrayIndex)
120         {
121             ProtoPreconditions.CheckNotNull(array, nameof(array));
122             if (arrayIndex < 0 || arrayIndex >= array.Length)
123                 throw new ArgumentOutOfRangeException(nameof(arrayIndex));
124             if (array.Length - arrayIndex < Count)
125                 throw new ArgumentException("The provided array is shorter than the number of elements in the registry");
126 
127             for (int i = 0; i < array.Length; i++)
128             {
129                 Extension extension = array[i];
130                 extensions.Add(new ObjectIntPair<Type>(extension.TargetType, extension.FieldNumber), extension);
131             }
132         }
133 
134         /// <summary>
135         /// Returns an enumerator to enumerate through the items in the registry
136         /// </summary>
137         /// <returns>Returns an enumerator for the extensions in this registry</returns>
GetEnumerator()138         public IEnumerator<Extension> GetEnumerator()
139         {
140             return extensions.Values.GetEnumerator();
141         }
142 
143         /// <summary>
144         /// Removes the specified extension from the set
145         /// </summary>
146         /// <param name="item">The extension</param>
147         /// <returns><c>true</c> if the extension was removed, otherwise <c>false</c></returns>
Remove(Extension item)148         public bool Remove(Extension item)
149         {
150             ProtoPreconditions.CheckNotNull(item, nameof(item));
151 
152             return extensions.Remove(new ObjectIntPair<Type>(item.TargetType, item.FieldNumber));
153         }
154 
IEnumerable.GetEnumerator()155         IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
156 
157         /// <summary>
158         /// Clones the registry into a new registry
159         /// </summary>
Clone()160         public ExtensionRegistry Clone()
161         {
162             return new ExtensionRegistry(extensions);
163         }
164     }
165 }
166