• 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 //
5 // Use of this source code is governed by a BSD-style
6 // license that can be found in the LICENSE file or at
7 // https://developers.google.com/open-source/licenses/bsd
8 #endregion
9 
10 using System;
11 using System.Collections;
12 using System.Collections.Generic;
13 using System.Linq;
14 
15 namespace Google.Protobuf
16 {
17     /// <summary>
18     /// Provides extensions to messages while parsing. This API is experimental and subject to change.
19     /// </summary>
20     public sealed class ExtensionRegistry : ICollection<Extension>, IDeepCloneable<ExtensionRegistry>
21     {
22         internal sealed class ExtensionComparer : IEqualityComparer<Extension>
23         {
Equals(Extension a, Extension b)24             public bool Equals(Extension a, Extension b)
25             {
26                 return new ObjectIntPair<Type>(a.TargetType, a.FieldNumber).Equals(new ObjectIntPair<Type>(b.TargetType, b.FieldNumber));
27             }
GetHashCode(Extension a)28             public int GetHashCode(Extension a)
29             {
30                 return new ObjectIntPair<Type>(a.TargetType, a.FieldNumber).GetHashCode();
31             }
32 
33             internal static ExtensionComparer Instance = new ExtensionComparer();
34         }
35         private readonly IDictionary<ObjectIntPair<Type>, Extension> extensions;
36 
37         /// <summary>
38         /// Creates a new empty extension registry
39         /// </summary>
ExtensionRegistry()40         public ExtensionRegistry()
41         {
42             extensions = new Dictionary<ObjectIntPair<Type>, Extension>();
43         }
44 
ExtensionRegistry(IDictionary<ObjectIntPair<Type>, Extension> collection)45         private ExtensionRegistry(IDictionary<ObjectIntPair<Type>, Extension> collection)
46         {
47             extensions = collection.ToDictionary(k => k.Key, v => v.Value);
48         }
49 
50         /// <summary>
51         /// Gets the total number of extensions in this extension registry
52         /// </summary>
53         public int Count => extensions.Count;
54 
55         /// <summary>
56         /// Returns whether the registry is readonly
57         /// </summary>
58         bool ICollection<Extension>.IsReadOnly => false;
59 
ContainsInputField(uint lastTag, Type target, out Extension extension)60         internal bool ContainsInputField(uint lastTag, Type target, out Extension extension)
61         {
62             return extensions.TryGetValue(new ObjectIntPair<Type>(target, WireFormat.GetTagFieldNumber(lastTag)), out extension);
63         }
64 
65         /// <summary>
66         /// Adds the specified extension to the registry
67         /// </summary>
Add(Extension extension)68         public void Add(Extension extension)
69         {
70             ProtoPreconditions.CheckNotNull(extension, nameof(extension));
71 
72             extensions.Add(new ObjectIntPair<Type>(extension.TargetType, extension.FieldNumber), extension);
73         }
74 
75         /// <summary>
76         /// Adds the specified extensions to the registry
77         /// </summary>
AddRange(IEnumerable<Extension> extensions)78         public void AddRange(IEnumerable<Extension> extensions)
79         {
80             ProtoPreconditions.CheckNotNull(extensions, nameof(extensions));
81 
82             foreach (var extension in extensions)
83             {
84                 Add(extension);
85             }
86         }
87 
88         /// <summary>
89         /// Clears the registry of all values
90         /// </summary>
Clear()91         public void Clear()
92         {
93             extensions.Clear();
94         }
95 
96         /// <summary>
97         /// Gets whether the extension registry contains the specified extension
98         /// </summary>
Contains(Extension item)99         public bool Contains(Extension item)
100         {
101             ProtoPreconditions.CheckNotNull(item, nameof(item));
102 
103             return extensions.ContainsKey(new ObjectIntPair<Type>(item.TargetType, item.FieldNumber));
104         }
105 
106         /// <summary>
107         /// Copies the arrays in the registry set to the specified array at the specified index
108         /// </summary>
109         /// <param name="array">The array to copy to</param>
110         /// <param name="arrayIndex">The array index to start at</param>
CopyTo(Extension[] array, int arrayIndex)111         void ICollection<Extension>.CopyTo(Extension[] array, int arrayIndex)
112         {
113             ProtoPreconditions.CheckNotNull(array, nameof(array));
114             if (arrayIndex < 0 || arrayIndex >= array.Length)
115             {
116                 throw new ArgumentOutOfRangeException(nameof(arrayIndex));
117             }
118             if (array.Length - arrayIndex < Count)
119             {
120                 throw new ArgumentException("The provided array is shorter than the number of elements in the registry");
121             }
122 
123             for (int i = 0; i < array.Length; i++)
124             {
125                 Extension extension = array[i];
126                 extensions.Add(new ObjectIntPair<Type>(extension.TargetType, extension.FieldNumber), extension);
127             }
128         }
129 
130         /// <summary>
131         /// Returns an enumerator to enumerate through the items in the registry
132         /// </summary>
133         /// <returns>Returns an enumerator for the extensions in this registry</returns>
GetEnumerator()134         public IEnumerator<Extension> GetEnumerator()
135         {
136             return extensions.Values.GetEnumerator();
137         }
138 
139         /// <summary>
140         /// Removes the specified extension from the set
141         /// </summary>
142         /// <param name="item">The extension</param>
143         /// <returns><c>true</c> if the extension was removed, otherwise <c>false</c></returns>
Remove(Extension item)144         public bool Remove(Extension item)
145         {
146             ProtoPreconditions.CheckNotNull(item, nameof(item));
147 
148             return extensions.Remove(new ObjectIntPair<Type>(item.TargetType, item.FieldNumber));
149         }
150 
IEnumerable.GetEnumerator()151         IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
152 
153         /// <summary>
154         /// Clones the registry into a new registry
155         /// </summary>
Clone()156         public ExtensionRegistry Clone()
157         {
158             return new ExtensionRegistry(extensions);
159         }
160     }
161 }
162