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 2017 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 Google.Protobuf.Collections; 34*1b3f573fSAndroid Build Coastguard Worker using System; 35*1b3f573fSAndroid Build Coastguard Worker using System.Collections; 36*1b3f573fSAndroid Build Coastguard Worker using System.Collections.Generic; 37*1b3f573fSAndroid Build Coastguard Worker using System.Diagnostics.CodeAnalysis; 38*1b3f573fSAndroid Build Coastguard Worker using System.Linq; 39*1b3f573fSAndroid Build Coastguard Worker using System.Reflection; 40*1b3f573fSAndroid Build Coastguard Worker 41*1b3f573fSAndroid Build Coastguard Worker namespace Google.Protobuf.Reflection 42*1b3f573fSAndroid Build Coastguard Worker { 43*1b3f573fSAndroid Build Coastguard Worker /// <summary> 44*1b3f573fSAndroid Build Coastguard Worker /// Container for a set of custom options specified within a message, field etc. 45*1b3f573fSAndroid Build Coastguard Worker /// </summary> 46*1b3f573fSAndroid Build Coastguard Worker /// <remarks> 47*1b3f573fSAndroid Build Coastguard Worker /// <para> 48*1b3f573fSAndroid Build Coastguard Worker /// This type is publicly immutable, but internally mutable. It is only populated 49*1b3f573fSAndroid Build Coastguard Worker /// by the descriptor parsing code - by the time any user code is able to see an instance, 50*1b3f573fSAndroid Build Coastguard Worker /// it will be fully initialized. 51*1b3f573fSAndroid Build Coastguard Worker /// </para> 52*1b3f573fSAndroid Build Coastguard Worker /// <para> 53*1b3f573fSAndroid Build Coastguard Worker /// If an option is requested using the incorrect method, an answer may still be returned: all 54*1b3f573fSAndroid Build Coastguard Worker /// of the numeric types are represented internally using 64-bit integers, for example. It is up to 55*1b3f573fSAndroid Build Coastguard Worker /// the caller to ensure that they make the appropriate method call for the option they're interested in. 56*1b3f573fSAndroid Build Coastguard Worker /// Note that enum options are simply stored as integers, so the value should be fetched using 57*1b3f573fSAndroid Build Coastguard Worker /// <see cref="TryGetInt32(int, out int)"/> and then cast appropriately. 58*1b3f573fSAndroid Build Coastguard Worker /// </para> 59*1b3f573fSAndroid Build Coastguard Worker /// <para> 60*1b3f573fSAndroid Build Coastguard Worker /// Repeated options are currently not supported. Asking for a single value of an option 61*1b3f573fSAndroid Build Coastguard Worker /// which was actually repeated will return the last value, except for message types where 62*1b3f573fSAndroid Build Coastguard Worker /// all the set values are merged together. 63*1b3f573fSAndroid Build Coastguard Worker /// </para> 64*1b3f573fSAndroid Build Coastguard Worker /// </remarks> 65*1b3f573fSAndroid Build Coastguard Worker public sealed class CustomOptions 66*1b3f573fSAndroid Build Coastguard Worker { 67*1b3f573fSAndroid Build Coastguard Worker private const string UnreferencedCodeMessage = "CustomOptions is incompatible with trimming."; 68*1b3f573fSAndroid Build Coastguard Worker 69*1b3f573fSAndroid Build Coastguard Worker private static readonly object[] EmptyParameters = new object[0]; 70*1b3f573fSAndroid Build Coastguard Worker private readonly IDictionary<int, IExtensionValue> values; 71*1b3f573fSAndroid Build Coastguard Worker CustomOptions(IDictionary<int, IExtensionValue> values)72*1b3f573fSAndroid Build Coastguard Worker internal CustomOptions(IDictionary<int, IExtensionValue> values) 73*1b3f573fSAndroid Build Coastguard Worker { 74*1b3f573fSAndroid Build Coastguard Worker this.values = values; 75*1b3f573fSAndroid Build Coastguard Worker } 76*1b3f573fSAndroid Build Coastguard Worker 77*1b3f573fSAndroid Build Coastguard Worker /// <summary> 78*1b3f573fSAndroid Build Coastguard Worker /// Retrieves a Boolean value for the specified option field. 79*1b3f573fSAndroid Build Coastguard Worker /// </summary> 80*1b3f573fSAndroid Build Coastguard Worker /// <param name="field">The field to fetch the value for.</param> 81*1b3f573fSAndroid Build Coastguard Worker /// <param name="value">The output variable to populate.</param> 82*1b3f573fSAndroid Build Coastguard Worker /// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns> 83*1b3f573fSAndroid Build Coastguard Worker [RequiresUnreferencedCode(UnreferencedCodeMessage)] TryGetBool(int field, out bool value)84*1b3f573fSAndroid Build Coastguard Worker public bool TryGetBool(int field, out bool value) => TryGetPrimitiveValue(field, out value); 85*1b3f573fSAndroid Build Coastguard Worker 86*1b3f573fSAndroid Build Coastguard Worker /// <summary> 87*1b3f573fSAndroid Build Coastguard Worker /// Retrieves a signed 32-bit integer value for the specified option field. 88*1b3f573fSAndroid Build Coastguard Worker /// </summary> 89*1b3f573fSAndroid Build Coastguard Worker /// <param name="field">The field to fetch the value for.</param> 90*1b3f573fSAndroid Build Coastguard Worker /// <param name="value">The output variable to populate.</param> 91*1b3f573fSAndroid Build Coastguard Worker /// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns> 92*1b3f573fSAndroid Build Coastguard Worker [RequiresUnreferencedCode(UnreferencedCodeMessage)] TryGetInt32(int field, out int value)93*1b3f573fSAndroid Build Coastguard Worker public bool TryGetInt32(int field, out int value) => TryGetPrimitiveValue(field, out value); 94*1b3f573fSAndroid Build Coastguard Worker 95*1b3f573fSAndroid Build Coastguard Worker /// <summary> 96*1b3f573fSAndroid Build Coastguard Worker /// Retrieves a signed 64-bit integer value for the specified option field. 97*1b3f573fSAndroid Build Coastguard Worker /// </summary> 98*1b3f573fSAndroid Build Coastguard Worker /// <param name="field">The field to fetch the value for.</param> 99*1b3f573fSAndroid Build Coastguard Worker /// <param name="value">The output variable to populate.</param> 100*1b3f573fSAndroid Build Coastguard Worker /// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns> 101*1b3f573fSAndroid Build Coastguard Worker [RequiresUnreferencedCode(UnreferencedCodeMessage)] TryGetInt64(int field, out long value)102*1b3f573fSAndroid Build Coastguard Worker public bool TryGetInt64(int field, out long value) => TryGetPrimitiveValue(field, out value); 103*1b3f573fSAndroid Build Coastguard Worker 104*1b3f573fSAndroid Build Coastguard Worker /// <summary> 105*1b3f573fSAndroid Build Coastguard Worker /// Retrieves an unsigned 32-bit integer value for the specified option field, 106*1b3f573fSAndroid Build Coastguard Worker /// assuming a fixed-length representation. 107*1b3f573fSAndroid Build Coastguard Worker /// </summary> 108*1b3f573fSAndroid Build Coastguard Worker /// <param name="field">The field to fetch the value for.</param> 109*1b3f573fSAndroid Build Coastguard Worker /// <param name="value">The output variable to populate.</param> 110*1b3f573fSAndroid Build Coastguard Worker /// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns> 111*1b3f573fSAndroid Build Coastguard Worker [RequiresUnreferencedCode(UnreferencedCodeMessage)] TryGetFixed32(int field, out uint value)112*1b3f573fSAndroid Build Coastguard Worker public bool TryGetFixed32(int field, out uint value) => TryGetUInt32(field, out value); 113*1b3f573fSAndroid Build Coastguard Worker 114*1b3f573fSAndroid Build Coastguard Worker /// <summary> 115*1b3f573fSAndroid Build Coastguard Worker /// Retrieves an unsigned 64-bit integer value for the specified option field, 116*1b3f573fSAndroid Build Coastguard Worker /// assuming a fixed-length representation. 117*1b3f573fSAndroid Build Coastguard Worker /// </summary> 118*1b3f573fSAndroid Build Coastguard Worker /// <param name="field">The field to fetch the value for.</param> 119*1b3f573fSAndroid Build Coastguard Worker /// <param name="value">The output variable to populate.</param> 120*1b3f573fSAndroid Build Coastguard Worker /// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns> 121*1b3f573fSAndroid Build Coastguard Worker [RequiresUnreferencedCode(UnreferencedCodeMessage)] TryGetFixed64(int field, out ulong value)122*1b3f573fSAndroid Build Coastguard Worker public bool TryGetFixed64(int field, out ulong value) => TryGetUInt64(field, out value); 123*1b3f573fSAndroid Build Coastguard Worker 124*1b3f573fSAndroid Build Coastguard Worker /// <summary> 125*1b3f573fSAndroid Build Coastguard Worker /// Retrieves a signed 32-bit integer value for the specified option field, 126*1b3f573fSAndroid Build Coastguard Worker /// assuming a fixed-length representation. 127*1b3f573fSAndroid Build Coastguard Worker /// </summary> 128*1b3f573fSAndroid Build Coastguard Worker /// <param name="field">The field to fetch the value for.</param> 129*1b3f573fSAndroid Build Coastguard Worker /// <param name="value">The output variable to populate.</param> 130*1b3f573fSAndroid Build Coastguard Worker /// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns> 131*1b3f573fSAndroid Build Coastguard Worker [RequiresUnreferencedCode(UnreferencedCodeMessage)] TryGetSFixed32(int field, out int value)132*1b3f573fSAndroid Build Coastguard Worker public bool TryGetSFixed32(int field, out int value) => TryGetInt32(field, out value); 133*1b3f573fSAndroid Build Coastguard Worker 134*1b3f573fSAndroid Build Coastguard Worker /// <summary> 135*1b3f573fSAndroid Build Coastguard Worker /// Retrieves a signed 64-bit integer value for the specified option field, 136*1b3f573fSAndroid Build Coastguard Worker /// assuming a fixed-length representation. 137*1b3f573fSAndroid Build Coastguard Worker /// </summary> 138*1b3f573fSAndroid Build Coastguard Worker /// <param name="field">The field to fetch the value for.</param> 139*1b3f573fSAndroid Build Coastguard Worker /// <param name="value">The output variable to populate.</param> 140*1b3f573fSAndroid Build Coastguard Worker /// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns> 141*1b3f573fSAndroid Build Coastguard Worker [RequiresUnreferencedCode(UnreferencedCodeMessage)] TryGetSFixed64(int field, out long value)142*1b3f573fSAndroid Build Coastguard Worker public bool TryGetSFixed64(int field, out long value) => TryGetInt64(field, out value); 143*1b3f573fSAndroid Build Coastguard Worker 144*1b3f573fSAndroid Build Coastguard Worker /// <summary> 145*1b3f573fSAndroid Build Coastguard Worker /// Retrieves a signed 32-bit integer value for the specified option field, 146*1b3f573fSAndroid Build Coastguard Worker /// assuming a zigzag encoding. 147*1b3f573fSAndroid Build Coastguard Worker /// </summary> 148*1b3f573fSAndroid Build Coastguard Worker /// <param name="field">The field to fetch the value for.</param> 149*1b3f573fSAndroid Build Coastguard Worker /// <param name="value">The output variable to populate.</param> 150*1b3f573fSAndroid Build Coastguard Worker /// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns> 151*1b3f573fSAndroid Build Coastguard Worker [RequiresUnreferencedCode(UnreferencedCodeMessage)] TryGetSInt32(int field, out int value)152*1b3f573fSAndroid Build Coastguard Worker public bool TryGetSInt32(int field, out int value) => TryGetPrimitiveValue(field, out value); 153*1b3f573fSAndroid Build Coastguard Worker 154*1b3f573fSAndroid Build Coastguard Worker /// <summary> 155*1b3f573fSAndroid Build Coastguard Worker /// Retrieves a signed 64-bit integer value for the specified option field, 156*1b3f573fSAndroid Build Coastguard Worker /// assuming a zigzag encoding. 157*1b3f573fSAndroid Build Coastguard Worker /// </summary> 158*1b3f573fSAndroid Build Coastguard Worker /// <param name="field">The field to fetch the value for.</param> 159*1b3f573fSAndroid Build Coastguard Worker /// <param name="value">The output variable to populate.</param> 160*1b3f573fSAndroid Build Coastguard Worker /// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns> 161*1b3f573fSAndroid Build Coastguard Worker [RequiresUnreferencedCode(UnreferencedCodeMessage)] TryGetSInt64(int field, out long value)162*1b3f573fSAndroid Build Coastguard Worker public bool TryGetSInt64(int field, out long value) => TryGetPrimitiveValue(field, out value); 163*1b3f573fSAndroid Build Coastguard Worker 164*1b3f573fSAndroid Build Coastguard Worker /// <summary> 165*1b3f573fSAndroid Build Coastguard Worker /// Retrieves an unsigned 32-bit integer value for the specified option field. 166*1b3f573fSAndroid Build Coastguard Worker /// </summary> 167*1b3f573fSAndroid Build Coastguard Worker /// <param name="field">The field to fetch the value for.</param> 168*1b3f573fSAndroid Build Coastguard Worker /// <param name="value">The output variable to populate.</param> 169*1b3f573fSAndroid Build Coastguard Worker /// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns> 170*1b3f573fSAndroid Build Coastguard Worker [RequiresUnreferencedCode(UnreferencedCodeMessage)] TryGetUInt32(int field, out uint value)171*1b3f573fSAndroid Build Coastguard Worker public bool TryGetUInt32(int field, out uint value) => TryGetPrimitiveValue(field, out value); 172*1b3f573fSAndroid Build Coastguard Worker 173*1b3f573fSAndroid Build Coastguard Worker /// <summary> 174*1b3f573fSAndroid Build Coastguard Worker /// Retrieves an unsigned 64-bit integer value for the specified option field. 175*1b3f573fSAndroid Build Coastguard Worker /// </summary> 176*1b3f573fSAndroid Build Coastguard Worker /// <param name="field">The field to fetch the value for.</param> 177*1b3f573fSAndroid Build Coastguard Worker /// <param name="value">The output variable to populate.</param> 178*1b3f573fSAndroid Build Coastguard Worker /// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns> 179*1b3f573fSAndroid Build Coastguard Worker [RequiresUnreferencedCode(UnreferencedCodeMessage)] TryGetUInt64(int field, out ulong value)180*1b3f573fSAndroid Build Coastguard Worker public bool TryGetUInt64(int field, out ulong value) => TryGetPrimitiveValue(field, out value); 181*1b3f573fSAndroid Build Coastguard Worker 182*1b3f573fSAndroid Build Coastguard Worker /// <summary> 183*1b3f573fSAndroid Build Coastguard Worker /// Retrieves a 32-bit floating point value for the specified option field. 184*1b3f573fSAndroid Build Coastguard Worker /// </summary> 185*1b3f573fSAndroid Build Coastguard Worker /// <param name="field">The field to fetch the value for.</param> 186*1b3f573fSAndroid Build Coastguard Worker /// <param name="value">The output variable to populate.</param> 187*1b3f573fSAndroid Build Coastguard Worker /// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns> 188*1b3f573fSAndroid Build Coastguard Worker [RequiresUnreferencedCode(UnreferencedCodeMessage)] TryGetFloat(int field, out float value)189*1b3f573fSAndroid Build Coastguard Worker public bool TryGetFloat(int field, out float value) => TryGetPrimitiveValue(field, out value); 190*1b3f573fSAndroid Build Coastguard Worker 191*1b3f573fSAndroid Build Coastguard Worker /// <summary> 192*1b3f573fSAndroid Build Coastguard Worker /// Retrieves a 64-bit floating point value for the specified option field. 193*1b3f573fSAndroid Build Coastguard Worker /// </summary> 194*1b3f573fSAndroid Build Coastguard Worker /// <param name="field">The field to fetch the value for.</param> 195*1b3f573fSAndroid Build Coastguard Worker /// <param name="value">The output variable to populate.</param> 196*1b3f573fSAndroid Build Coastguard Worker /// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns> 197*1b3f573fSAndroid Build Coastguard Worker [RequiresUnreferencedCode(UnreferencedCodeMessage)] TryGetDouble(int field, out double value)198*1b3f573fSAndroid Build Coastguard Worker public bool TryGetDouble(int field, out double value) => TryGetPrimitiveValue(field, out value); 199*1b3f573fSAndroid Build Coastguard Worker 200*1b3f573fSAndroid Build Coastguard Worker /// <summary> 201*1b3f573fSAndroid Build Coastguard Worker /// Retrieves a string value for the specified option field. 202*1b3f573fSAndroid Build Coastguard Worker /// </summary> 203*1b3f573fSAndroid Build Coastguard Worker /// <param name="field">The field to fetch the value for.</param> 204*1b3f573fSAndroid Build Coastguard Worker /// <param name="value">The output variable to populate.</param> 205*1b3f573fSAndroid Build Coastguard Worker /// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns> 206*1b3f573fSAndroid Build Coastguard Worker [RequiresUnreferencedCode(UnreferencedCodeMessage)] TryGetString(int field, out string value)207*1b3f573fSAndroid Build Coastguard Worker public bool TryGetString(int field, out string value) => TryGetPrimitiveValue(field, out value); 208*1b3f573fSAndroid Build Coastguard Worker 209*1b3f573fSAndroid Build Coastguard Worker /// <summary> 210*1b3f573fSAndroid Build Coastguard Worker /// Retrieves a bytes value for the specified option field. 211*1b3f573fSAndroid Build Coastguard Worker /// </summary> 212*1b3f573fSAndroid Build Coastguard Worker /// <param name="field">The field to fetch the value for.</param> 213*1b3f573fSAndroid Build Coastguard Worker /// <param name="value">The output variable to populate.</param> 214*1b3f573fSAndroid Build Coastguard Worker /// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns> 215*1b3f573fSAndroid Build Coastguard Worker [RequiresUnreferencedCode(UnreferencedCodeMessage)] TryGetBytes(int field, out ByteString value)216*1b3f573fSAndroid Build Coastguard Worker public bool TryGetBytes(int field, out ByteString value) => TryGetPrimitiveValue(field, out value); 217*1b3f573fSAndroid Build Coastguard Worker 218*1b3f573fSAndroid Build Coastguard Worker /// <summary> 219*1b3f573fSAndroid Build Coastguard Worker /// Retrieves a message value for the specified option field. 220*1b3f573fSAndroid Build Coastguard Worker /// </summary> 221*1b3f573fSAndroid Build Coastguard Worker /// <param name="field">The field to fetch the value for.</param> 222*1b3f573fSAndroid Build Coastguard Worker /// <param name="value">The output variable to populate.</param> 223*1b3f573fSAndroid Build Coastguard Worker /// <returns><c>true</c> if a suitable value for the field was found; <c>false</c> otherwise.</returns> 224*1b3f573fSAndroid Build Coastguard Worker [RequiresUnreferencedCode(UnreferencedCodeMessage)] 225*1b3f573fSAndroid Build Coastguard Worker public bool TryGetMessage<T>(int field, out T value) where T : class, IMessage, new() 226*1b3f573fSAndroid Build Coastguard Worker { 227*1b3f573fSAndroid Build Coastguard Worker if (values == null) 228*1b3f573fSAndroid Build Coastguard Worker { 229*1b3f573fSAndroid Build Coastguard Worker value = default(T); 230*1b3f573fSAndroid Build Coastguard Worker return false; 231*1b3f573fSAndroid Build Coastguard Worker } 232*1b3f573fSAndroid Build Coastguard Worker 233*1b3f573fSAndroid Build Coastguard Worker IExtensionValue extensionValue; 234*1b3f573fSAndroid Build Coastguard Worker if (values.TryGetValue(field, out extensionValue)) 235*1b3f573fSAndroid Build Coastguard Worker { 236*1b3f573fSAndroid Build Coastguard Worker if (extensionValue is ExtensionValue<T>) 237*1b3f573fSAndroid Build Coastguard Worker { 238*1b3f573fSAndroid Build Coastguard Worker ExtensionValue<T> single = extensionValue as ExtensionValue<T>; 239*1b3f573fSAndroid Build Coastguard Worker ByteString bytes = single.GetValue().ToByteString(); 240*1b3f573fSAndroid Build Coastguard Worker value = new T(); 241*1b3f573fSAndroid Build Coastguard Worker value.MergeFrom(bytes); 242*1b3f573fSAndroid Build Coastguard Worker return true; 243*1b3f573fSAndroid Build Coastguard Worker } 244*1b3f573fSAndroid Build Coastguard Worker else if (extensionValue is RepeatedExtensionValue<T>) 245*1b3f573fSAndroid Build Coastguard Worker { 246*1b3f573fSAndroid Build Coastguard Worker RepeatedExtensionValue<T> repeated = extensionValue as RepeatedExtensionValue<T>; 247*1b3f573fSAndroid Build Coastguard Worker value = repeated.GetValue() 248*1b3f573fSAndroid Build Coastguard Worker .Select(v => v.ToByteString()) 249*1b3f573fSAndroid Build Coastguard Worker .Aggregate(new T(), (t, b) => 250*1b3f573fSAndroid Build Coastguard Worker { 251*1b3f573fSAndroid Build Coastguard Worker t.MergeFrom(b); 252*1b3f573fSAndroid Build Coastguard Worker return t; 253*1b3f573fSAndroid Build Coastguard Worker }); 254*1b3f573fSAndroid Build Coastguard Worker return true; 255*1b3f573fSAndroid Build Coastguard Worker } 256*1b3f573fSAndroid Build Coastguard Worker } 257*1b3f573fSAndroid Build Coastguard Worker 258*1b3f573fSAndroid Build Coastguard Worker value = null; 259*1b3f573fSAndroid Build Coastguard Worker return false; 260*1b3f573fSAndroid Build Coastguard Worker } 261*1b3f573fSAndroid Build Coastguard Worker 262*1b3f573fSAndroid Build Coastguard Worker [RequiresUnreferencedCode(UnreferencedCodeMessage)] TryGetPrimitiveValue(int field, out T value)263*1b3f573fSAndroid Build Coastguard Worker private bool TryGetPrimitiveValue<T>(int field, out T value) 264*1b3f573fSAndroid Build Coastguard Worker { 265*1b3f573fSAndroid Build Coastguard Worker if (values == null) 266*1b3f573fSAndroid Build Coastguard Worker { 267*1b3f573fSAndroid Build Coastguard Worker value = default(T); 268*1b3f573fSAndroid Build Coastguard Worker return false; 269*1b3f573fSAndroid Build Coastguard Worker } 270*1b3f573fSAndroid Build Coastguard Worker 271*1b3f573fSAndroid Build Coastguard Worker IExtensionValue extensionValue; 272*1b3f573fSAndroid Build Coastguard Worker if (values.TryGetValue(field, out extensionValue)) 273*1b3f573fSAndroid Build Coastguard Worker { 274*1b3f573fSAndroid Build Coastguard Worker if (extensionValue is ExtensionValue<T>) 275*1b3f573fSAndroid Build Coastguard Worker { 276*1b3f573fSAndroid Build Coastguard Worker ExtensionValue<T> single = extensionValue as ExtensionValue<T>; 277*1b3f573fSAndroid Build Coastguard Worker value = single.GetValue(); 278*1b3f573fSAndroid Build Coastguard Worker return true; 279*1b3f573fSAndroid Build Coastguard Worker } 280*1b3f573fSAndroid Build Coastguard Worker else if (extensionValue is RepeatedExtensionValue<T>) 281*1b3f573fSAndroid Build Coastguard Worker { 282*1b3f573fSAndroid Build Coastguard Worker RepeatedExtensionValue<T> repeated = extensionValue as RepeatedExtensionValue<T>; 283*1b3f573fSAndroid Build Coastguard Worker if (repeated.GetValue().Count != 0) 284*1b3f573fSAndroid Build Coastguard Worker { 285*1b3f573fSAndroid Build Coastguard Worker RepeatedField<T> repeatedField = repeated.GetValue(); 286*1b3f573fSAndroid Build Coastguard Worker value = repeatedField[repeatedField.Count - 1]; 287*1b3f573fSAndroid Build Coastguard Worker return true; 288*1b3f573fSAndroid Build Coastguard Worker } 289*1b3f573fSAndroid Build Coastguard Worker } 290*1b3f573fSAndroid Build Coastguard Worker else // and here we find explicit enum handling since T : Enum ! x is ExtensionValue<Enum> 291*1b3f573fSAndroid Build Coastguard Worker { 292*1b3f573fSAndroid Build Coastguard Worker var type = extensionValue.GetType(); 293*1b3f573fSAndroid Build Coastguard Worker if (type.GetGenericTypeDefinition() == typeof(ExtensionValue<>)) 294*1b3f573fSAndroid Build Coastguard Worker { 295*1b3f573fSAndroid Build Coastguard Worker var typeInfo = type.GetTypeInfo(); 296*1b3f573fSAndroid Build Coastguard Worker var typeArgs = typeInfo.GenericTypeArguments; 297*1b3f573fSAndroid Build Coastguard Worker if (typeArgs.Length == 1 && typeArgs[0].GetTypeInfo().IsEnum) 298*1b3f573fSAndroid Build Coastguard Worker { 299*1b3f573fSAndroid Build Coastguard Worker value = (T)typeInfo.GetDeclaredMethod(nameof(ExtensionValue<T>.GetValue)).Invoke(extensionValue, EmptyParameters); 300*1b3f573fSAndroid Build Coastguard Worker return true; 301*1b3f573fSAndroid Build Coastguard Worker } 302*1b3f573fSAndroid Build Coastguard Worker } 303*1b3f573fSAndroid Build Coastguard Worker else if (type.GetGenericTypeDefinition() == typeof(RepeatedExtensionValue<>)) 304*1b3f573fSAndroid Build Coastguard Worker { 305*1b3f573fSAndroid Build Coastguard Worker var typeInfo = type.GetTypeInfo(); 306*1b3f573fSAndroid Build Coastguard Worker var typeArgs = typeInfo.GenericTypeArguments; 307*1b3f573fSAndroid Build Coastguard Worker if (typeArgs.Length == 1 && typeArgs[0].GetTypeInfo().IsEnum) 308*1b3f573fSAndroid Build Coastguard Worker { 309*1b3f573fSAndroid Build Coastguard Worker var values = (IList)typeInfo.GetDeclaredMethod(nameof(RepeatedExtensionValue<T>.GetValue)).Invoke(extensionValue, EmptyParameters); 310*1b3f573fSAndroid Build Coastguard Worker if (values.Count != 0) 311*1b3f573fSAndroid Build Coastguard Worker { 312*1b3f573fSAndroid Build Coastguard Worker value = (T)values[values.Count - 1]; 313*1b3f573fSAndroid Build Coastguard Worker return true; 314*1b3f573fSAndroid Build Coastguard Worker } 315*1b3f573fSAndroid Build Coastguard Worker } 316*1b3f573fSAndroid Build Coastguard Worker } 317*1b3f573fSAndroid Build Coastguard Worker } 318*1b3f573fSAndroid Build Coastguard Worker } 319*1b3f573fSAndroid Build Coastguard Worker 320*1b3f573fSAndroid Build Coastguard Worker value = default(T); 321*1b3f573fSAndroid Build Coastguard Worker return false; 322*1b3f573fSAndroid Build Coastguard Worker } 323*1b3f573fSAndroid Build Coastguard Worker } 324*1b3f573fSAndroid Build Coastguard Worker } 325