1ffe3c632Sopenharmony_ci#region Copyright notice and license
2ffe3c632Sopenharmony_ci// Protocol Buffers - Google's data interchange format
3ffe3c632Sopenharmony_ci// Copyright 2008 Google Inc.  All rights reserved.
4ffe3c632Sopenharmony_ci// https://developers.google.com/protocol-buffers/
5ffe3c632Sopenharmony_ci//
6ffe3c632Sopenharmony_ci// Redistribution and use in source and binary forms, with or without
7ffe3c632Sopenharmony_ci// modification, are permitted provided that the following conditions are
8ffe3c632Sopenharmony_ci// met:
9ffe3c632Sopenharmony_ci//
10ffe3c632Sopenharmony_ci//     * Redistributions of source code must retain the above copyright
11ffe3c632Sopenharmony_ci// notice, this list of conditions and the following disclaimer.
12ffe3c632Sopenharmony_ci//     * Redistributions in binary form must reproduce the above
13ffe3c632Sopenharmony_ci// copyright notice, this list of conditions and the following disclaimer
14ffe3c632Sopenharmony_ci// in the documentation and/or other materials provided with the
15ffe3c632Sopenharmony_ci// distribution.
16ffe3c632Sopenharmony_ci//     * Neither the name of Google Inc. nor the names of its
17ffe3c632Sopenharmony_ci// contributors may be used to endorse or promote products derived from
18ffe3c632Sopenharmony_ci// this software without specific prior written permission.
19ffe3c632Sopenharmony_ci//
20ffe3c632Sopenharmony_ci// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21ffe3c632Sopenharmony_ci// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22ffe3c632Sopenharmony_ci// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23ffe3c632Sopenharmony_ci// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24ffe3c632Sopenharmony_ci// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25ffe3c632Sopenharmony_ci// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26ffe3c632Sopenharmony_ci// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27ffe3c632Sopenharmony_ci// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28ffe3c632Sopenharmony_ci// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29ffe3c632Sopenharmony_ci// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30ffe3c632Sopenharmony_ci// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31ffe3c632Sopenharmony_ci#endregion
32ffe3c632Sopenharmony_ci
33ffe3c632Sopenharmony_ciusing Google.Protobuf.Collections;
34ffe3c632Sopenharmony_ciusing System;
35ffe3c632Sopenharmony_ciusing System.Collections.Generic;
36ffe3c632Sopenharmony_ciusing System.Linq;
37ffe3c632Sopenharmony_ciusing System.Security;
38ffe3c632Sopenharmony_ci
39ffe3c632Sopenharmony_cinamespace Google.Protobuf
40ffe3c632Sopenharmony_ci{
41ffe3c632Sopenharmony_ci    /// <summary>
42ffe3c632Sopenharmony_ci    /// Methods for managing <see cref="ExtensionSet{TTarget}"/>s with null checking.
43ffe3c632Sopenharmony_ci    ///
44ffe3c632Sopenharmony_ci    /// Most users will not use this class directly and its API is experimental and subject to change.
45ffe3c632Sopenharmony_ci    /// </summary>
46ffe3c632Sopenharmony_ci    public static class ExtensionSet
47ffe3c632Sopenharmony_ci    {
48ffe3c632Sopenharmony_ci        private static bool TryGetValue<TTarget>(ref ExtensionSet<TTarget> set, Extension extension, out IExtensionValue value) where TTarget : IExtendableMessage<TTarget>
49ffe3c632Sopenharmony_ci        {
50ffe3c632Sopenharmony_ci            if (set == null)
51ffe3c632Sopenharmony_ci            {
52ffe3c632Sopenharmony_ci                value = null;
53ffe3c632Sopenharmony_ci                return false;
54ffe3c632Sopenharmony_ci            }
55ffe3c632Sopenharmony_ci            return set.ValuesByNumber.TryGetValue(extension.FieldNumber, out value);
56ffe3c632Sopenharmony_ci        }
57ffe3c632Sopenharmony_ci
58ffe3c632Sopenharmony_ci        /// <summary>
59ffe3c632Sopenharmony_ci        /// Gets the value of the specified extension
60ffe3c632Sopenharmony_ci        /// </summary>
61ffe3c632Sopenharmony_ci        public static TValue Get<TTarget, TValue>(ref ExtensionSet<TTarget> set, Extension<TTarget, TValue> extension) where TTarget : IExtendableMessage<TTarget>
62ffe3c632Sopenharmony_ci        {
63ffe3c632Sopenharmony_ci            IExtensionValue value;
64ffe3c632Sopenharmony_ci            if (TryGetValue(ref set, extension, out value))
65ffe3c632Sopenharmony_ci            {
66ffe3c632Sopenharmony_ci                return ((ExtensionValue<TValue>)value).GetValue();
67ffe3c632Sopenharmony_ci            }
68ffe3c632Sopenharmony_ci            else
69ffe3c632Sopenharmony_ci            {
70ffe3c632Sopenharmony_ci                return extension.DefaultValue;
71ffe3c632Sopenharmony_ci            }
72ffe3c632Sopenharmony_ci        }
73ffe3c632Sopenharmony_ci
74ffe3c632Sopenharmony_ci        /// <summary>
75ffe3c632Sopenharmony_ci        /// Gets the value of the specified repeated extension or null if it doesn't exist in this set
76ffe3c632Sopenharmony_ci        /// </summary>
77ffe3c632Sopenharmony_ci        public static RepeatedField<TValue> Get<TTarget, TValue>(ref ExtensionSet<TTarget> set, RepeatedExtension<TTarget, TValue> extension) where TTarget : IExtendableMessage<TTarget>
78ffe3c632Sopenharmony_ci        {
79ffe3c632Sopenharmony_ci            IExtensionValue value;
80ffe3c632Sopenharmony_ci            if (TryGetValue(ref set, extension, out value))
81ffe3c632Sopenharmony_ci            {
82ffe3c632Sopenharmony_ci                return ((RepeatedExtensionValue<TValue>)value).GetValue();
83ffe3c632Sopenharmony_ci            }
84ffe3c632Sopenharmony_ci            else
85ffe3c632Sopenharmony_ci            {
86ffe3c632Sopenharmony_ci                return null;
87ffe3c632Sopenharmony_ci            }
88ffe3c632Sopenharmony_ci        }
89ffe3c632Sopenharmony_ci
90ffe3c632Sopenharmony_ci        /// <summary>
91ffe3c632Sopenharmony_ci        /// Gets the value of the specified repeated extension, registering it if it doesn't exist
92ffe3c632Sopenharmony_ci        /// </summary>
93ffe3c632Sopenharmony_ci        public static RepeatedField<TValue> GetOrInitialize<TTarget, TValue>(ref ExtensionSet<TTarget> set, RepeatedExtension<TTarget, TValue> extension) where TTarget : IExtendableMessage<TTarget>
94ffe3c632Sopenharmony_ci        {
95ffe3c632Sopenharmony_ci            IExtensionValue value;
96ffe3c632Sopenharmony_ci            if (set == null)
97ffe3c632Sopenharmony_ci            {
98ffe3c632Sopenharmony_ci                value = extension.CreateValue();
99ffe3c632Sopenharmony_ci                set = new ExtensionSet<TTarget>();
100ffe3c632Sopenharmony_ci                set.ValuesByNumber.Add(extension.FieldNumber, value);
101ffe3c632Sopenharmony_ci            }
102ffe3c632Sopenharmony_ci            else
103ffe3c632Sopenharmony_ci            {
104ffe3c632Sopenharmony_ci                if (!set.ValuesByNumber.TryGetValue(extension.FieldNumber, out value))
105ffe3c632Sopenharmony_ci                {
106ffe3c632Sopenharmony_ci                    value = extension.CreateValue();
107ffe3c632Sopenharmony_ci                    set.ValuesByNumber.Add(extension.FieldNumber, value);
108ffe3c632Sopenharmony_ci                }
109ffe3c632Sopenharmony_ci            }
110ffe3c632Sopenharmony_ci
111ffe3c632Sopenharmony_ci            return ((RepeatedExtensionValue<TValue>)value).GetValue();
112ffe3c632Sopenharmony_ci        }
113ffe3c632Sopenharmony_ci
114ffe3c632Sopenharmony_ci        /// <summary>
115ffe3c632Sopenharmony_ci        /// Sets the value of the specified extension. This will make a new instance of ExtensionSet if the set is null.
116ffe3c632Sopenharmony_ci        /// </summary>
117ffe3c632Sopenharmony_ci        public static void Set<TTarget, TValue>(ref ExtensionSet<TTarget> set, Extension<TTarget, TValue> extension, TValue value) where TTarget : IExtendableMessage<TTarget>
118ffe3c632Sopenharmony_ci        {
119ffe3c632Sopenharmony_ci            ProtoPreconditions.CheckNotNullUnconstrained(value, nameof(value));
120ffe3c632Sopenharmony_ci
121ffe3c632Sopenharmony_ci            IExtensionValue extensionValue;
122ffe3c632Sopenharmony_ci            if (set == null)
123ffe3c632Sopenharmony_ci            {
124ffe3c632Sopenharmony_ci                extensionValue = extension.CreateValue();
125ffe3c632Sopenharmony_ci                set = new ExtensionSet<TTarget>();
126ffe3c632Sopenharmony_ci                set.ValuesByNumber.Add(extension.FieldNumber, extensionValue);
127ffe3c632Sopenharmony_ci            }
128ffe3c632Sopenharmony_ci            else
129ffe3c632Sopenharmony_ci            {
130ffe3c632Sopenharmony_ci                if (!set.ValuesByNumber.TryGetValue(extension.FieldNumber, out extensionValue))
131ffe3c632Sopenharmony_ci                {
132ffe3c632Sopenharmony_ci                    extensionValue = extension.CreateValue();
133ffe3c632Sopenharmony_ci                    set.ValuesByNumber.Add(extension.FieldNumber, extensionValue);
134ffe3c632Sopenharmony_ci                }
135ffe3c632Sopenharmony_ci            }
136ffe3c632Sopenharmony_ci
137ffe3c632Sopenharmony_ci            ((ExtensionValue<TValue>)extensionValue).SetValue(value);
138ffe3c632Sopenharmony_ci        }
139ffe3c632Sopenharmony_ci
140ffe3c632Sopenharmony_ci        /// <summary>
141ffe3c632Sopenharmony_ci        /// Gets whether the value of the specified extension is set
142ffe3c632Sopenharmony_ci        /// </summary>
143ffe3c632Sopenharmony_ci        public static bool Has<TTarget, TValue>(ref ExtensionSet<TTarget> set, Extension<TTarget, TValue> extension) where TTarget : IExtendableMessage<TTarget>
144ffe3c632Sopenharmony_ci        {
145ffe3c632Sopenharmony_ci            IExtensionValue value;
146ffe3c632Sopenharmony_ci            return TryGetValue(ref set, extension, out value);
147ffe3c632Sopenharmony_ci        }
148ffe3c632Sopenharmony_ci
149ffe3c632Sopenharmony_ci        /// <summary>
150ffe3c632Sopenharmony_ci        /// Clears the value of the specified extension
151ffe3c632Sopenharmony_ci        /// </summary>
152ffe3c632Sopenharmony_ci        public static void Clear<TTarget, TValue>(ref ExtensionSet<TTarget> set, Extension<TTarget, TValue> extension) where TTarget : IExtendableMessage<TTarget>
153ffe3c632Sopenharmony_ci        {
154ffe3c632Sopenharmony_ci            if (set == null)
155ffe3c632Sopenharmony_ci            {
156ffe3c632Sopenharmony_ci                return;
157ffe3c632Sopenharmony_ci            }
158ffe3c632Sopenharmony_ci            set.ValuesByNumber.Remove(extension.FieldNumber);
159ffe3c632Sopenharmony_ci            if (set.ValuesByNumber.Count == 0)
160ffe3c632Sopenharmony_ci            {
161ffe3c632Sopenharmony_ci                set = null;
162ffe3c632Sopenharmony_ci            }
163ffe3c632Sopenharmony_ci        }
164ffe3c632Sopenharmony_ci
165ffe3c632Sopenharmony_ci        /// <summary>
166ffe3c632Sopenharmony_ci        /// Clears the value of the specified extension
167ffe3c632Sopenharmony_ci        /// </summary>
168ffe3c632Sopenharmony_ci        public static void Clear<TTarget, TValue>(ref ExtensionSet<TTarget> set, RepeatedExtension<TTarget, TValue> extension) where TTarget : IExtendableMessage<TTarget>
169ffe3c632Sopenharmony_ci        {
170ffe3c632Sopenharmony_ci            if (set == null)
171ffe3c632Sopenharmony_ci            {
172ffe3c632Sopenharmony_ci                return;
173ffe3c632Sopenharmony_ci            }
174ffe3c632Sopenharmony_ci            set.ValuesByNumber.Remove(extension.FieldNumber);
175ffe3c632Sopenharmony_ci            if (set.ValuesByNumber.Count == 0)
176ffe3c632Sopenharmony_ci            {
177ffe3c632Sopenharmony_ci                set = null;
178ffe3c632Sopenharmony_ci            }
179ffe3c632Sopenharmony_ci        }
180ffe3c632Sopenharmony_ci
181ffe3c632Sopenharmony_ci        /// <summary>
182ffe3c632Sopenharmony_ci        /// Tries to merge a field from the coded input, returning true if the field was merged.
183ffe3c632Sopenharmony_ci        /// If the set is null or the field was not otherwise merged, this returns false.
184ffe3c632Sopenharmony_ci        /// </summary>
185ffe3c632Sopenharmony_ci        public static bool TryMergeFieldFrom<TTarget>(ref ExtensionSet<TTarget> set, CodedInputStream stream) where TTarget : IExtendableMessage<TTarget>
186ffe3c632Sopenharmony_ci        {
187ffe3c632Sopenharmony_ci            ParseContext.Initialize(stream, out ParseContext ctx);
188ffe3c632Sopenharmony_ci            try
189ffe3c632Sopenharmony_ci            {
190ffe3c632Sopenharmony_ci                return TryMergeFieldFrom<TTarget>(ref set, ref ctx);
191ffe3c632Sopenharmony_ci            }
192ffe3c632Sopenharmony_ci            finally
193ffe3c632Sopenharmony_ci            {
194ffe3c632Sopenharmony_ci                ctx.CopyStateTo(stream);
195ffe3c632Sopenharmony_ci            }
196ffe3c632Sopenharmony_ci        }
197ffe3c632Sopenharmony_ci
198ffe3c632Sopenharmony_ci        /// <summary>
199ffe3c632Sopenharmony_ci        /// Tries to merge a field from the coded input, returning true if the field was merged.
200ffe3c632Sopenharmony_ci        /// If the set is null or the field was not otherwise merged, this returns false.
201ffe3c632Sopenharmony_ci        /// </summary>
202ffe3c632Sopenharmony_ci        public static bool TryMergeFieldFrom<TTarget>(ref ExtensionSet<TTarget> set, ref ParseContext ctx) where TTarget : IExtendableMessage<TTarget>
203ffe3c632Sopenharmony_ci        {
204ffe3c632Sopenharmony_ci            Extension extension;
205ffe3c632Sopenharmony_ci            int lastFieldNumber = WireFormat.GetTagFieldNumber(ctx.LastTag);
206ffe3c632Sopenharmony_ci
207ffe3c632Sopenharmony_ci            IExtensionValue extensionValue;
208ffe3c632Sopenharmony_ci            if (set != null && set.ValuesByNumber.TryGetValue(lastFieldNumber, out extensionValue))
209ffe3c632Sopenharmony_ci            {
210ffe3c632Sopenharmony_ci                extensionValue.MergeFrom(ref ctx);
211ffe3c632Sopenharmony_ci                return true;
212ffe3c632Sopenharmony_ci            }
213ffe3c632Sopenharmony_ci            else if (ctx.ExtensionRegistry != null && ctx.ExtensionRegistry.ContainsInputField(ctx.LastTag, typeof(TTarget), out extension))
214ffe3c632Sopenharmony_ci            {
215ffe3c632Sopenharmony_ci                IExtensionValue value = extension.CreateValue();
216ffe3c632Sopenharmony_ci                value.MergeFrom(ref ctx);
217ffe3c632Sopenharmony_ci                set = (set ?? new ExtensionSet<TTarget>());
218ffe3c632Sopenharmony_ci                set.ValuesByNumber.Add(extension.FieldNumber, value);
219ffe3c632Sopenharmony_ci                return true;
220ffe3c632Sopenharmony_ci            }
221ffe3c632Sopenharmony_ci            else
222ffe3c632Sopenharmony_ci            {
223ffe3c632Sopenharmony_ci                return false;
224ffe3c632Sopenharmony_ci            }
225ffe3c632Sopenharmony_ci        }
226ffe3c632Sopenharmony_ci
227ffe3c632Sopenharmony_ci        /// <summary>
228ffe3c632Sopenharmony_ci        /// Merges the second set into the first set, creating a new instance if first is null
229ffe3c632Sopenharmony_ci        /// </summary>
230ffe3c632Sopenharmony_ci        public static void MergeFrom<TTarget>(ref ExtensionSet<TTarget> first, ExtensionSet<TTarget> second) where TTarget : IExtendableMessage<TTarget>
231ffe3c632Sopenharmony_ci        {
232ffe3c632Sopenharmony_ci            if (second == null)
233ffe3c632Sopenharmony_ci            {
234ffe3c632Sopenharmony_ci                return;
235ffe3c632Sopenharmony_ci            }
236ffe3c632Sopenharmony_ci            if (first == null)
237ffe3c632Sopenharmony_ci            {
238ffe3c632Sopenharmony_ci                first = new ExtensionSet<TTarget>();
239ffe3c632Sopenharmony_ci            }
240ffe3c632Sopenharmony_ci            foreach (var pair in second.ValuesByNumber)
241ffe3c632Sopenharmony_ci            {
242ffe3c632Sopenharmony_ci                IExtensionValue value;
243ffe3c632Sopenharmony_ci                if (first.ValuesByNumber.TryGetValue(pair.Key, out value))
244ffe3c632Sopenharmony_ci                {
245ffe3c632Sopenharmony_ci                    value.MergeFrom(pair.Value);
246ffe3c632Sopenharmony_ci                }
247ffe3c632Sopenharmony_ci                else
248ffe3c632Sopenharmony_ci                {
249ffe3c632Sopenharmony_ci                    var cloned = pair.Value.Clone();
250ffe3c632Sopenharmony_ci                    first.ValuesByNumber[pair.Key] = cloned;
251ffe3c632Sopenharmony_ci                }
252ffe3c632Sopenharmony_ci            }
253ffe3c632Sopenharmony_ci        }
254ffe3c632Sopenharmony_ci
255ffe3c632Sopenharmony_ci        /// <summary>
256ffe3c632Sopenharmony_ci        /// Clones the set into a new set. If the set is null, this returns null
257ffe3c632Sopenharmony_ci        /// </summary>
258ffe3c632Sopenharmony_ci        public static ExtensionSet<TTarget> Clone<TTarget>(ExtensionSet<TTarget> set) where TTarget : IExtendableMessage<TTarget>
259ffe3c632Sopenharmony_ci        {
260ffe3c632Sopenharmony_ci            if (set == null)
261ffe3c632Sopenharmony_ci            {
262ffe3c632Sopenharmony_ci                return null;
263ffe3c632Sopenharmony_ci            }
264ffe3c632Sopenharmony_ci
265ffe3c632Sopenharmony_ci            var newSet = new ExtensionSet<TTarget>();
266ffe3c632Sopenharmony_ci            foreach (var pair in set.ValuesByNumber)
267ffe3c632Sopenharmony_ci            {
268ffe3c632Sopenharmony_ci                var cloned = pair.Value.Clone();
269ffe3c632Sopenharmony_ci                newSet.ValuesByNumber[pair.Key] = cloned;
270ffe3c632Sopenharmony_ci            }
271ffe3c632Sopenharmony_ci            return newSet;
272ffe3c632Sopenharmony_ci        }
273ffe3c632Sopenharmony_ci    }
274ffe3c632Sopenharmony_ci
275ffe3c632Sopenharmony_ci    /// <summary>
276ffe3c632Sopenharmony_ci    /// Used for keeping track of extensions in messages.
277ffe3c632Sopenharmony_ci    /// <see cref="IExtendableMessage{T}"/> methods route to this set.
278ffe3c632Sopenharmony_ci    ///
279ffe3c632Sopenharmony_ci    /// Most users will not need to use this class directly
280ffe3c632Sopenharmony_ci    /// </summary>
281ffe3c632Sopenharmony_ci    /// <typeparam name="TTarget">The message type that extensions in this set target</typeparam>
282ffe3c632Sopenharmony_ci    public sealed class ExtensionSet<TTarget> where TTarget : IExtendableMessage<TTarget>
283ffe3c632Sopenharmony_ci    {
284ffe3c632Sopenharmony_ci        internal Dictionary<int, IExtensionValue> ValuesByNumber { get; } = new Dictionary<int, IExtensionValue>();
285ffe3c632Sopenharmony_ci
286ffe3c632Sopenharmony_ci        /// <summary>
287ffe3c632Sopenharmony_ci        /// Gets a hash code of the set
288ffe3c632Sopenharmony_ci        /// </summary>
289ffe3c632Sopenharmony_ci        public override int GetHashCode()
290ffe3c632Sopenharmony_ci        {
291ffe3c632Sopenharmony_ci            int ret = typeof(TTarget).GetHashCode();
292ffe3c632Sopenharmony_ci            foreach (KeyValuePair<int, IExtensionValue> field in ValuesByNumber)
293ffe3c632Sopenharmony_ci            {
294ffe3c632Sopenharmony_ci                // Use ^ here to make the field order irrelevant.
295ffe3c632Sopenharmony_ci                int hash = field.Key.GetHashCode() ^ field.Value.GetHashCode();
296ffe3c632Sopenharmony_ci                ret ^= hash;
297ffe3c632Sopenharmony_ci            }
298ffe3c632Sopenharmony_ci            return ret;
299ffe3c632Sopenharmony_ci        }
300ffe3c632Sopenharmony_ci
301ffe3c632Sopenharmony_ci        /// <summary>
302ffe3c632Sopenharmony_ci        /// Returns whether this set is equal to the other object
303ffe3c632Sopenharmony_ci        /// </summary>
304ffe3c632Sopenharmony_ci        public override bool Equals(object other)
305ffe3c632Sopenharmony_ci        {
306ffe3c632Sopenharmony_ci            if (ReferenceEquals(this, other))
307ffe3c632Sopenharmony_ci            {
308ffe3c632Sopenharmony_ci                return true;
309ffe3c632Sopenharmony_ci            }
310ffe3c632Sopenharmony_ci            ExtensionSet<TTarget> otherSet = other as ExtensionSet<TTarget>;
311ffe3c632Sopenharmony_ci            if (ValuesByNumber.Count != otherSet.ValuesByNumber.Count)
312ffe3c632Sopenharmony_ci            {
313ffe3c632Sopenharmony_ci                return false;
314ffe3c632Sopenharmony_ci            }
315ffe3c632Sopenharmony_ci            foreach (var pair in ValuesByNumber)
316ffe3c632Sopenharmony_ci            {
317ffe3c632Sopenharmony_ci                IExtensionValue secondValue;
318ffe3c632Sopenharmony_ci                if (!otherSet.ValuesByNumber.TryGetValue(pair.Key, out secondValue))
319ffe3c632Sopenharmony_ci                {
320ffe3c632Sopenharmony_ci                    return false;
321ffe3c632Sopenharmony_ci                }
322ffe3c632Sopenharmony_ci                if (!pair.Value.Equals(secondValue))
323ffe3c632Sopenharmony_ci                {
324ffe3c632Sopenharmony_ci                    return false;
325ffe3c632Sopenharmony_ci                }
326ffe3c632Sopenharmony_ci            }
327ffe3c632Sopenharmony_ci            return true;
328ffe3c632Sopenharmony_ci        }
329ffe3c632Sopenharmony_ci
330ffe3c632Sopenharmony_ci        /// <summary>
331ffe3c632Sopenharmony_ci        /// Calculates the size of this extension set
332ffe3c632Sopenharmony_ci        /// </summary>
333ffe3c632Sopenharmony_ci        public int CalculateSize()
334ffe3c632Sopenharmony_ci        {
335ffe3c632Sopenharmony_ci            int size = 0;
336ffe3c632Sopenharmony_ci            foreach (var value in ValuesByNumber.Values)
337ffe3c632Sopenharmony_ci            {
338ffe3c632Sopenharmony_ci                size += value.CalculateSize();
339ffe3c632Sopenharmony_ci            }
340ffe3c632Sopenharmony_ci            return size;
341ffe3c632Sopenharmony_ci        }
342ffe3c632Sopenharmony_ci
343ffe3c632Sopenharmony_ci        /// <summary>
344ffe3c632Sopenharmony_ci        /// Writes the extension values in this set to the output stream
345ffe3c632Sopenharmony_ci        /// </summary>
346ffe3c632Sopenharmony_ci        public void WriteTo(CodedOutputStream stream)
347ffe3c632Sopenharmony_ci        {
348ffe3c632Sopenharmony_ci
349ffe3c632Sopenharmony_ci            WriteContext.Initialize(stream, out WriteContext ctx);
350ffe3c632Sopenharmony_ci            try
351ffe3c632Sopenharmony_ci            {
352ffe3c632Sopenharmony_ci                WriteTo(ref ctx);
353ffe3c632Sopenharmony_ci            }
354ffe3c632Sopenharmony_ci            finally
355ffe3c632Sopenharmony_ci            {
356ffe3c632Sopenharmony_ci                ctx.CopyStateTo(stream);
357ffe3c632Sopenharmony_ci            }
358ffe3c632Sopenharmony_ci        }
359ffe3c632Sopenharmony_ci
360ffe3c632Sopenharmony_ci        /// <summary>
361ffe3c632Sopenharmony_ci        /// Writes the extension values in this set to the write context
362ffe3c632Sopenharmony_ci        /// </summary>
363ffe3c632Sopenharmony_ci        [SecuritySafeCritical]
364ffe3c632Sopenharmony_ci        public void WriteTo(ref WriteContext ctx)
365ffe3c632Sopenharmony_ci        {
366ffe3c632Sopenharmony_ci            foreach (var value in ValuesByNumber.Values)
367ffe3c632Sopenharmony_ci            {
368ffe3c632Sopenharmony_ci                value.WriteTo(ref ctx);
369ffe3c632Sopenharmony_ci            }
370ffe3c632Sopenharmony_ci        }
371ffe3c632Sopenharmony_ci
372ffe3c632Sopenharmony_ci        internal bool IsInitialized()
373ffe3c632Sopenharmony_ci        {
374ffe3c632Sopenharmony_ci            return ValuesByNumber.Values.All(v => v.IsInitialized());
375ffe3c632Sopenharmony_ci        }
376ffe3c632Sopenharmony_ci    }
377ffe3c632Sopenharmony_ci}
378