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