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 2015 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.Reflection; 34*1b3f573fSAndroid Build Coastguard Worker using System.Buffers; 35*1b3f573fSAndroid Build Coastguard Worker using System.Collections; 36*1b3f573fSAndroid Build Coastguard Worker using System; 37*1b3f573fSAndroid Build Coastguard Worker using System.IO; 38*1b3f573fSAndroid Build Coastguard Worker using System.Linq; 39*1b3f573fSAndroid Build Coastguard Worker using System.Security; 40*1b3f573fSAndroid Build Coastguard Worker 41*1b3f573fSAndroid Build Coastguard Worker namespace Google.Protobuf 42*1b3f573fSAndroid Build Coastguard Worker { 43*1b3f573fSAndroid Build Coastguard Worker /// <summary> 44*1b3f573fSAndroid Build Coastguard Worker /// Extension methods on <see cref="IMessage"/> and <see cref="IMessage{T}"/>. 45*1b3f573fSAndroid Build Coastguard Worker /// </summary> 46*1b3f573fSAndroid Build Coastguard Worker public static class MessageExtensions 47*1b3f573fSAndroid Build Coastguard Worker { 48*1b3f573fSAndroid Build Coastguard Worker /// <summary> 49*1b3f573fSAndroid Build Coastguard Worker /// Merges data from the given byte array into an existing message. 50*1b3f573fSAndroid Build Coastguard Worker /// </summary> 51*1b3f573fSAndroid Build Coastguard Worker /// <param name="message">The message to merge the data into.</param> 52*1b3f573fSAndroid Build Coastguard Worker /// <param name="data">The data to merge, which must be protobuf-encoded binary data.</param> MergeFrom(this IMessage message, byte[] data)53*1b3f573fSAndroid Build Coastguard Worker public static void MergeFrom(this IMessage message, byte[] data) => 54*1b3f573fSAndroid Build Coastguard Worker MergeFrom(message, data, false, null); 55*1b3f573fSAndroid Build Coastguard Worker 56*1b3f573fSAndroid Build Coastguard Worker /// <summary> 57*1b3f573fSAndroid Build Coastguard Worker /// Merges data from the given byte array slice into an existing message. 58*1b3f573fSAndroid Build Coastguard Worker /// </summary> 59*1b3f573fSAndroid Build Coastguard Worker /// <param name="message">The message to merge the data into.</param> 60*1b3f573fSAndroid Build Coastguard Worker /// <param name="data">The data containing the slice to merge, which must be protobuf-encoded binary data.</param> 61*1b3f573fSAndroid Build Coastguard Worker /// <param name="offset">The offset of the slice to merge.</param> 62*1b3f573fSAndroid Build Coastguard Worker /// <param name="length">The length of the slice to merge.</param> MergeFrom(this IMessage message, byte[] data, int offset, int length)63*1b3f573fSAndroid Build Coastguard Worker public static void MergeFrom(this IMessage message, byte[] data, int offset, int length) => 64*1b3f573fSAndroid Build Coastguard Worker MergeFrom(message, data, offset, length, false, null); 65*1b3f573fSAndroid Build Coastguard Worker 66*1b3f573fSAndroid Build Coastguard Worker /// <summary> 67*1b3f573fSAndroid Build Coastguard Worker /// Merges data from the given byte string into an existing message. 68*1b3f573fSAndroid Build Coastguard Worker /// </summary> 69*1b3f573fSAndroid Build Coastguard Worker /// <param name="message">The message to merge the data into.</param> 70*1b3f573fSAndroid Build Coastguard Worker /// <param name="data">The data to merge, which must be protobuf-encoded binary data.</param> MergeFrom(this IMessage message, ByteString data)71*1b3f573fSAndroid Build Coastguard Worker public static void MergeFrom(this IMessage message, ByteString data) => 72*1b3f573fSAndroid Build Coastguard Worker MergeFrom(message, data, false, null); 73*1b3f573fSAndroid Build Coastguard Worker 74*1b3f573fSAndroid Build Coastguard Worker /// <summary> 75*1b3f573fSAndroid Build Coastguard Worker /// Merges data from the given stream into an existing message. 76*1b3f573fSAndroid Build Coastguard Worker /// </summary> 77*1b3f573fSAndroid Build Coastguard Worker /// <param name="message">The message to merge the data into.</param> 78*1b3f573fSAndroid Build Coastguard Worker /// <param name="input">Stream containing the data to merge, which must be protobuf-encoded binary data.</param> MergeFrom(this IMessage message, Stream input)79*1b3f573fSAndroid Build Coastguard Worker public static void MergeFrom(this IMessage message, Stream input) => 80*1b3f573fSAndroid Build Coastguard Worker MergeFrom(message, input, false, null); 81*1b3f573fSAndroid Build Coastguard Worker 82*1b3f573fSAndroid Build Coastguard Worker /// <summary> 83*1b3f573fSAndroid Build Coastguard Worker /// Merges data from the given span into an existing message. 84*1b3f573fSAndroid Build Coastguard Worker /// </summary> 85*1b3f573fSAndroid Build Coastguard Worker /// <param name="message">The message to merge the data into.</param> 86*1b3f573fSAndroid Build Coastguard Worker /// <param name="span">Span containing the data to merge, which must be protobuf-encoded binary data.</param> 87*1b3f573fSAndroid Build Coastguard Worker [SecuritySafeCritical] MergeFrom(this IMessage message, ReadOnlySpan<byte> span)88*1b3f573fSAndroid Build Coastguard Worker public static void MergeFrom(this IMessage message, ReadOnlySpan<byte> span) => 89*1b3f573fSAndroid Build Coastguard Worker MergeFrom(message, span, false, null); 90*1b3f573fSAndroid Build Coastguard Worker 91*1b3f573fSAndroid Build Coastguard Worker /// <summary> 92*1b3f573fSAndroid Build Coastguard Worker /// Merges length-delimited data from the given stream into an existing message. 93*1b3f573fSAndroid Build Coastguard Worker /// </summary> 94*1b3f573fSAndroid Build Coastguard Worker /// <remarks> 95*1b3f573fSAndroid Build Coastguard Worker /// The stream is expected to contain a length and then the data. Only the amount of data 96*1b3f573fSAndroid Build Coastguard Worker /// specified by the length will be consumed. 97*1b3f573fSAndroid Build Coastguard Worker /// </remarks> 98*1b3f573fSAndroid Build Coastguard Worker /// <param name="message">The message to merge the data into.</param> 99*1b3f573fSAndroid Build Coastguard Worker /// <param name="input">Stream containing the data to merge, which must be protobuf-encoded binary data.</param> MergeDelimitedFrom(this IMessage message, Stream input)100*1b3f573fSAndroid Build Coastguard Worker public static void MergeDelimitedFrom(this IMessage message, Stream input) => 101*1b3f573fSAndroid Build Coastguard Worker MergeDelimitedFrom(message, input, false, null); 102*1b3f573fSAndroid Build Coastguard Worker 103*1b3f573fSAndroid Build Coastguard Worker /// <summary> 104*1b3f573fSAndroid Build Coastguard Worker /// Converts the given message into a byte array in protobuf encoding. 105*1b3f573fSAndroid Build Coastguard Worker /// </summary> 106*1b3f573fSAndroid Build Coastguard Worker /// <param name="message">The message to convert.</param> 107*1b3f573fSAndroid Build Coastguard Worker /// <returns>The message data as a byte array.</returns> ToByteArray(this IMessage message)108*1b3f573fSAndroid Build Coastguard Worker public static byte[] ToByteArray(this IMessage message) 109*1b3f573fSAndroid Build Coastguard Worker { 110*1b3f573fSAndroid Build Coastguard Worker ProtoPreconditions.CheckNotNull(message, "message"); 111*1b3f573fSAndroid Build Coastguard Worker byte[] result = new byte[message.CalculateSize()]; 112*1b3f573fSAndroid Build Coastguard Worker CodedOutputStream output = new CodedOutputStream(result); 113*1b3f573fSAndroid Build Coastguard Worker message.WriteTo(output); 114*1b3f573fSAndroid Build Coastguard Worker output.CheckNoSpaceLeft(); 115*1b3f573fSAndroid Build Coastguard Worker return result; 116*1b3f573fSAndroid Build Coastguard Worker } 117*1b3f573fSAndroid Build Coastguard Worker 118*1b3f573fSAndroid Build Coastguard Worker /// <summary> 119*1b3f573fSAndroid Build Coastguard Worker /// Writes the given message data to the given stream in protobuf encoding. 120*1b3f573fSAndroid Build Coastguard Worker /// </summary> 121*1b3f573fSAndroid Build Coastguard Worker /// <param name="message">The message to write to the stream.</param> 122*1b3f573fSAndroid Build Coastguard Worker /// <param name="output">The stream to write to.</param> WriteTo(this IMessage message, Stream output)123*1b3f573fSAndroid Build Coastguard Worker public static void WriteTo(this IMessage message, Stream output) 124*1b3f573fSAndroid Build Coastguard Worker { 125*1b3f573fSAndroid Build Coastguard Worker ProtoPreconditions.CheckNotNull(message, "message"); 126*1b3f573fSAndroid Build Coastguard Worker ProtoPreconditions.CheckNotNull(output, "output"); 127*1b3f573fSAndroid Build Coastguard Worker CodedOutputStream codedOutput = new CodedOutputStream(output); 128*1b3f573fSAndroid Build Coastguard Worker message.WriteTo(codedOutput); 129*1b3f573fSAndroid Build Coastguard Worker codedOutput.Flush(); 130*1b3f573fSAndroid Build Coastguard Worker } 131*1b3f573fSAndroid Build Coastguard Worker 132*1b3f573fSAndroid Build Coastguard Worker /// <summary> 133*1b3f573fSAndroid Build Coastguard Worker /// Writes the length and then data of the given message to a stream. 134*1b3f573fSAndroid Build Coastguard Worker /// </summary> 135*1b3f573fSAndroid Build Coastguard Worker /// <param name="message">The message to write.</param> 136*1b3f573fSAndroid Build Coastguard Worker /// <param name="output">The output stream to write to.</param> WriteDelimitedTo(this IMessage message, Stream output)137*1b3f573fSAndroid Build Coastguard Worker public static void WriteDelimitedTo(this IMessage message, Stream output) 138*1b3f573fSAndroid Build Coastguard Worker { 139*1b3f573fSAndroid Build Coastguard Worker ProtoPreconditions.CheckNotNull(message, "message"); 140*1b3f573fSAndroid Build Coastguard Worker ProtoPreconditions.CheckNotNull(output, "output"); 141*1b3f573fSAndroid Build Coastguard Worker CodedOutputStream codedOutput = new CodedOutputStream(output); 142*1b3f573fSAndroid Build Coastguard Worker codedOutput.WriteLength(message.CalculateSize()); 143*1b3f573fSAndroid Build Coastguard Worker message.WriteTo(codedOutput); 144*1b3f573fSAndroid Build Coastguard Worker codedOutput.Flush(); 145*1b3f573fSAndroid Build Coastguard Worker } 146*1b3f573fSAndroid Build Coastguard Worker 147*1b3f573fSAndroid Build Coastguard Worker /// <summary> 148*1b3f573fSAndroid Build Coastguard Worker /// Converts the given message into a byte string in protobuf encoding. 149*1b3f573fSAndroid Build Coastguard Worker /// </summary> 150*1b3f573fSAndroid Build Coastguard Worker /// <param name="message">The message to convert.</param> 151*1b3f573fSAndroid Build Coastguard Worker /// <returns>The message data as a byte string.</returns> ToByteString(this IMessage message)152*1b3f573fSAndroid Build Coastguard Worker public static ByteString ToByteString(this IMessage message) 153*1b3f573fSAndroid Build Coastguard Worker { 154*1b3f573fSAndroid Build Coastguard Worker ProtoPreconditions.CheckNotNull(message, "message"); 155*1b3f573fSAndroid Build Coastguard Worker return ByteString.AttachBytes(message.ToByteArray()); 156*1b3f573fSAndroid Build Coastguard Worker } 157*1b3f573fSAndroid Build Coastguard Worker 158*1b3f573fSAndroid Build Coastguard Worker /// <summary> 159*1b3f573fSAndroid Build Coastguard Worker /// Writes the given message data to the given buffer writer in protobuf encoding. 160*1b3f573fSAndroid Build Coastguard Worker /// </summary> 161*1b3f573fSAndroid Build Coastguard Worker /// <param name="message">The message to write to the stream.</param> 162*1b3f573fSAndroid Build Coastguard Worker /// <param name="output">The stream to write to.</param> 163*1b3f573fSAndroid Build Coastguard Worker [SecuritySafeCritical] WriteTo(this IMessage message, IBufferWriter<byte> output)164*1b3f573fSAndroid Build Coastguard Worker public static void WriteTo(this IMessage message, IBufferWriter<byte> output) 165*1b3f573fSAndroid Build Coastguard Worker { 166*1b3f573fSAndroid Build Coastguard Worker ProtoPreconditions.CheckNotNull(message, nameof(message)); 167*1b3f573fSAndroid Build Coastguard Worker ProtoPreconditions.CheckNotNull(output, nameof(output)); 168*1b3f573fSAndroid Build Coastguard Worker 169*1b3f573fSAndroid Build Coastguard Worker WriteContext.Initialize(output, out WriteContext ctx); 170*1b3f573fSAndroid Build Coastguard Worker WritingPrimitivesMessages.WriteRawMessage(ref ctx, message); 171*1b3f573fSAndroid Build Coastguard Worker ctx.Flush(); 172*1b3f573fSAndroid Build Coastguard Worker } 173*1b3f573fSAndroid Build Coastguard Worker 174*1b3f573fSAndroid Build Coastguard Worker /// <summary> 175*1b3f573fSAndroid Build Coastguard Worker /// Writes the given message data to the given span in protobuf encoding. 176*1b3f573fSAndroid Build Coastguard Worker /// The size of the destination span needs to fit the serialized size 177*1b3f573fSAndroid Build Coastguard Worker /// of the message exactly, otherwise an exception is thrown. 178*1b3f573fSAndroid Build Coastguard Worker /// </summary> 179*1b3f573fSAndroid Build Coastguard Worker /// <param name="message">The message to write to the stream.</param> 180*1b3f573fSAndroid Build Coastguard Worker /// <param name="output">The span to write to. Size must match size of the message exactly.</param> 181*1b3f573fSAndroid Build Coastguard Worker [SecuritySafeCritical] WriteTo(this IMessage message, Span<byte> output)182*1b3f573fSAndroid Build Coastguard Worker public static void WriteTo(this IMessage message, Span<byte> output) 183*1b3f573fSAndroid Build Coastguard Worker { 184*1b3f573fSAndroid Build Coastguard Worker ProtoPreconditions.CheckNotNull(message, nameof(message)); 185*1b3f573fSAndroid Build Coastguard Worker 186*1b3f573fSAndroid Build Coastguard Worker WriteContext.Initialize(ref output, out WriteContext ctx); 187*1b3f573fSAndroid Build Coastguard Worker WritingPrimitivesMessages.WriteRawMessage(ref ctx, message); 188*1b3f573fSAndroid Build Coastguard Worker ctx.CheckNoSpaceLeft(); 189*1b3f573fSAndroid Build Coastguard Worker } 190*1b3f573fSAndroid Build Coastguard Worker 191*1b3f573fSAndroid Build Coastguard Worker /// <summary> 192*1b3f573fSAndroid Build Coastguard Worker /// Checks if all required fields in a message have values set. For proto3 messages, this returns true 193*1b3f573fSAndroid Build Coastguard Worker /// </summary> IsInitialized(this IMessage message)194*1b3f573fSAndroid Build Coastguard Worker public static bool IsInitialized(this IMessage message) 195*1b3f573fSAndroid Build Coastguard Worker { 196*1b3f573fSAndroid Build Coastguard Worker if (message.Descriptor.File.Syntax == Syntax.Proto3) 197*1b3f573fSAndroid Build Coastguard Worker { 198*1b3f573fSAndroid Build Coastguard Worker return true; 199*1b3f573fSAndroid Build Coastguard Worker } 200*1b3f573fSAndroid Build Coastguard Worker 201*1b3f573fSAndroid Build Coastguard Worker if (!message.Descriptor.IsExtensionsInitialized(message)) 202*1b3f573fSAndroid Build Coastguard Worker { 203*1b3f573fSAndroid Build Coastguard Worker return false; 204*1b3f573fSAndroid Build Coastguard Worker } 205*1b3f573fSAndroid Build Coastguard Worker 206*1b3f573fSAndroid Build Coastguard Worker return message.Descriptor 207*1b3f573fSAndroid Build Coastguard Worker .Fields 208*1b3f573fSAndroid Build Coastguard Worker .InDeclarationOrder() 209*1b3f573fSAndroid Build Coastguard Worker .All(f => 210*1b3f573fSAndroid Build Coastguard Worker { 211*1b3f573fSAndroid Build Coastguard Worker if (f.IsMap) 212*1b3f573fSAndroid Build Coastguard Worker { 213*1b3f573fSAndroid Build Coastguard Worker var valueField = f.MessageType.Fields[2]; 214*1b3f573fSAndroid Build Coastguard Worker if (valueField.FieldType == FieldType.Message) 215*1b3f573fSAndroid Build Coastguard Worker { 216*1b3f573fSAndroid Build Coastguard Worker var map = (IDictionary)f.Accessor.GetValue(message); 217*1b3f573fSAndroid Build Coastguard Worker return map.Values.Cast<IMessage>().All(IsInitialized); 218*1b3f573fSAndroid Build Coastguard Worker } 219*1b3f573fSAndroid Build Coastguard Worker else 220*1b3f573fSAndroid Build Coastguard Worker { 221*1b3f573fSAndroid Build Coastguard Worker return true; 222*1b3f573fSAndroid Build Coastguard Worker } 223*1b3f573fSAndroid Build Coastguard Worker } 224*1b3f573fSAndroid Build Coastguard Worker else if (f.IsRepeated && f.FieldType == FieldType.Message || f.FieldType == FieldType.Group) 225*1b3f573fSAndroid Build Coastguard Worker { 226*1b3f573fSAndroid Build Coastguard Worker var enumerable = (IEnumerable)f.Accessor.GetValue(message); 227*1b3f573fSAndroid Build Coastguard Worker return enumerable.Cast<IMessage>().All(IsInitialized); 228*1b3f573fSAndroid Build Coastguard Worker } 229*1b3f573fSAndroid Build Coastguard Worker else if (f.FieldType == FieldType.Message || f.FieldType == FieldType.Group) 230*1b3f573fSAndroid Build Coastguard Worker { 231*1b3f573fSAndroid Build Coastguard Worker if (f.Accessor.HasValue(message)) 232*1b3f573fSAndroid Build Coastguard Worker { 233*1b3f573fSAndroid Build Coastguard Worker return ((IMessage)f.Accessor.GetValue(message)).IsInitialized(); 234*1b3f573fSAndroid Build Coastguard Worker } 235*1b3f573fSAndroid Build Coastguard Worker else 236*1b3f573fSAndroid Build Coastguard Worker { 237*1b3f573fSAndroid Build Coastguard Worker return !f.IsRequired; 238*1b3f573fSAndroid Build Coastguard Worker } 239*1b3f573fSAndroid Build Coastguard Worker } 240*1b3f573fSAndroid Build Coastguard Worker else if (f.IsRequired) 241*1b3f573fSAndroid Build Coastguard Worker { 242*1b3f573fSAndroid Build Coastguard Worker return f.Accessor.HasValue(message); 243*1b3f573fSAndroid Build Coastguard Worker } 244*1b3f573fSAndroid Build Coastguard Worker else 245*1b3f573fSAndroid Build Coastguard Worker { 246*1b3f573fSAndroid Build Coastguard Worker return true; 247*1b3f573fSAndroid Build Coastguard Worker } 248*1b3f573fSAndroid Build Coastguard Worker }); 249*1b3f573fSAndroid Build Coastguard Worker } 250*1b3f573fSAndroid Build Coastguard Worker 251*1b3f573fSAndroid Build Coastguard Worker // Implementations allowing unknown fields to be discarded. MergeFrom(this IMessage message, byte[] data, bool discardUnknownFields, ExtensionRegistry registry)252*1b3f573fSAndroid Build Coastguard Worker internal static void MergeFrom(this IMessage message, byte[] data, bool discardUnknownFields, ExtensionRegistry registry) 253*1b3f573fSAndroid Build Coastguard Worker { 254*1b3f573fSAndroid Build Coastguard Worker ProtoPreconditions.CheckNotNull(message, "message"); 255*1b3f573fSAndroid Build Coastguard Worker ProtoPreconditions.CheckNotNull(data, "data"); 256*1b3f573fSAndroid Build Coastguard Worker CodedInputStream input = new CodedInputStream(data); 257*1b3f573fSAndroid Build Coastguard Worker input.DiscardUnknownFields = discardUnknownFields; 258*1b3f573fSAndroid Build Coastguard Worker input.ExtensionRegistry = registry; 259*1b3f573fSAndroid Build Coastguard Worker message.MergeFrom(input); 260*1b3f573fSAndroid Build Coastguard Worker input.CheckReadEndOfStreamTag(); 261*1b3f573fSAndroid Build Coastguard Worker } 262*1b3f573fSAndroid Build Coastguard Worker MergeFrom(this IMessage message, byte[] data, int offset, int length, bool discardUnknownFields, ExtensionRegistry registry)263*1b3f573fSAndroid Build Coastguard Worker internal static void MergeFrom(this IMessage message, byte[] data, int offset, int length, bool discardUnknownFields, ExtensionRegistry registry) 264*1b3f573fSAndroid Build Coastguard Worker { 265*1b3f573fSAndroid Build Coastguard Worker ProtoPreconditions.CheckNotNull(message, "message"); 266*1b3f573fSAndroid Build Coastguard Worker ProtoPreconditions.CheckNotNull(data, "data"); 267*1b3f573fSAndroid Build Coastguard Worker CodedInputStream input = new CodedInputStream(data, offset, length); 268*1b3f573fSAndroid Build Coastguard Worker input.DiscardUnknownFields = discardUnknownFields; 269*1b3f573fSAndroid Build Coastguard Worker input.ExtensionRegistry = registry; 270*1b3f573fSAndroid Build Coastguard Worker message.MergeFrom(input); 271*1b3f573fSAndroid Build Coastguard Worker input.CheckReadEndOfStreamTag(); 272*1b3f573fSAndroid Build Coastguard Worker } 273*1b3f573fSAndroid Build Coastguard Worker MergeFrom(this IMessage message, ByteString data, bool discardUnknownFields, ExtensionRegistry registry)274*1b3f573fSAndroid Build Coastguard Worker internal static void MergeFrom(this IMessage message, ByteString data, bool discardUnknownFields, ExtensionRegistry registry) 275*1b3f573fSAndroid Build Coastguard Worker { 276*1b3f573fSAndroid Build Coastguard Worker ProtoPreconditions.CheckNotNull(message, "message"); 277*1b3f573fSAndroid Build Coastguard Worker ProtoPreconditions.CheckNotNull(data, "data"); 278*1b3f573fSAndroid Build Coastguard Worker CodedInputStream input = data.CreateCodedInput(); 279*1b3f573fSAndroid Build Coastguard Worker input.DiscardUnknownFields = discardUnknownFields; 280*1b3f573fSAndroid Build Coastguard Worker input.ExtensionRegistry = registry; 281*1b3f573fSAndroid Build Coastguard Worker message.MergeFrom(input); 282*1b3f573fSAndroid Build Coastguard Worker input.CheckReadEndOfStreamTag(); 283*1b3f573fSAndroid Build Coastguard Worker } 284*1b3f573fSAndroid Build Coastguard Worker MergeFrom(this IMessage message, Stream input, bool discardUnknownFields, ExtensionRegistry registry)285*1b3f573fSAndroid Build Coastguard Worker internal static void MergeFrom(this IMessage message, Stream input, bool discardUnknownFields, ExtensionRegistry registry) 286*1b3f573fSAndroid Build Coastguard Worker { 287*1b3f573fSAndroid Build Coastguard Worker ProtoPreconditions.CheckNotNull(message, "message"); 288*1b3f573fSAndroid Build Coastguard Worker ProtoPreconditions.CheckNotNull(input, "input"); 289*1b3f573fSAndroid Build Coastguard Worker CodedInputStream codedInput = new CodedInputStream(input); 290*1b3f573fSAndroid Build Coastguard Worker codedInput.DiscardUnknownFields = discardUnknownFields; 291*1b3f573fSAndroid Build Coastguard Worker codedInput.ExtensionRegistry = registry; 292*1b3f573fSAndroid Build Coastguard Worker message.MergeFrom(codedInput); 293*1b3f573fSAndroid Build Coastguard Worker codedInput.CheckReadEndOfStreamTag(); 294*1b3f573fSAndroid Build Coastguard Worker } 295*1b3f573fSAndroid Build Coastguard Worker 296*1b3f573fSAndroid Build Coastguard Worker [SecuritySafeCritical] MergeFrom(this IMessage message, ReadOnlySequence<byte> data, bool discardUnknownFields, ExtensionRegistry registry)297*1b3f573fSAndroid Build Coastguard Worker internal static void MergeFrom(this IMessage message, ReadOnlySequence<byte> data, bool discardUnknownFields, ExtensionRegistry registry) 298*1b3f573fSAndroid Build Coastguard Worker { 299*1b3f573fSAndroid Build Coastguard Worker ParseContext.Initialize(data, out ParseContext ctx); 300*1b3f573fSAndroid Build Coastguard Worker ctx.DiscardUnknownFields = discardUnknownFields; 301*1b3f573fSAndroid Build Coastguard Worker ctx.ExtensionRegistry = registry; 302*1b3f573fSAndroid Build Coastguard Worker ParsingPrimitivesMessages.ReadRawMessage(ref ctx, message); 303*1b3f573fSAndroid Build Coastguard Worker ParsingPrimitivesMessages.CheckReadEndOfStreamTag(ref ctx.state); 304*1b3f573fSAndroid Build Coastguard Worker } 305*1b3f573fSAndroid Build Coastguard Worker 306*1b3f573fSAndroid Build Coastguard Worker [SecuritySafeCritical] MergeFrom(this IMessage message, ReadOnlySpan<byte> data, bool discardUnknownFields, ExtensionRegistry registry)307*1b3f573fSAndroid Build Coastguard Worker internal static void MergeFrom(this IMessage message, ReadOnlySpan<byte> data, bool discardUnknownFields, ExtensionRegistry registry) 308*1b3f573fSAndroid Build Coastguard Worker { 309*1b3f573fSAndroid Build Coastguard Worker ParseContext.Initialize(data, out ParseContext ctx); 310*1b3f573fSAndroid Build Coastguard Worker ctx.DiscardUnknownFields = discardUnknownFields; 311*1b3f573fSAndroid Build Coastguard Worker ctx.ExtensionRegistry = registry; 312*1b3f573fSAndroid Build Coastguard Worker ParsingPrimitivesMessages.ReadRawMessage(ref ctx, message); 313*1b3f573fSAndroid Build Coastguard Worker ParsingPrimitivesMessages.CheckReadEndOfStreamTag(ref ctx.state); 314*1b3f573fSAndroid Build Coastguard Worker } 315*1b3f573fSAndroid Build Coastguard Worker MergeDelimitedFrom(this IMessage message, Stream input, bool discardUnknownFields, ExtensionRegistry registry)316*1b3f573fSAndroid Build Coastguard Worker internal static void MergeDelimitedFrom(this IMessage message, Stream input, bool discardUnknownFields, ExtensionRegistry registry) 317*1b3f573fSAndroid Build Coastguard Worker { 318*1b3f573fSAndroid Build Coastguard Worker ProtoPreconditions.CheckNotNull(message, "message"); 319*1b3f573fSAndroid Build Coastguard Worker ProtoPreconditions.CheckNotNull(input, "input"); 320*1b3f573fSAndroid Build Coastguard Worker int size = (int) CodedInputStream.ReadRawVarint32(input); 321*1b3f573fSAndroid Build Coastguard Worker Stream limitedStream = new LimitedInputStream(input, size); 322*1b3f573fSAndroid Build Coastguard Worker MergeFrom(message, limitedStream, discardUnknownFields, registry); 323*1b3f573fSAndroid Build Coastguard Worker } 324*1b3f573fSAndroid Build Coastguard Worker } 325*1b3f573fSAndroid Build Coastguard Worker } 326