blob: 62181eb9d9b344ce9318ec12bf91ad66d4118dac [file] [log] [blame]
Brian Silverman9c614bc2016-02-15 20:20:02 -05001#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
33using System.IO;
34
35namespace Google.Protobuf
36{
37 /// <summary>
38 /// Extension methods on <see cref="IMessage"/> and <see cref="IMessage{T}"/>.
39 /// </summary>
40 public static class MessageExtensions
41 {
42 /// <summary>
43 /// Merges data from the given byte array into an existing message.
44 /// </summary>
45 /// <param name="message">The message to merge the data into.</param>
46 /// <param name="data">The data to merge, which must be protobuf-encoded binary data.</param>
Austin Schuh40c16522018-10-28 20:27:54 -070047 public static void MergeFrom(this IMessage message, byte[] data) =>
48 MergeFrom(message, data, false);
49
50 /// <summary>
51 /// Merges data from the given byte array slice into an existing message.
52 /// </summary>
53 /// <param name="message">The message to merge the data into.</param>
54 /// <param name="data">The data containing the slice to merge, which must be protobuf-encoded binary data.</param>
55 /// <param name="offset">The offset of the slice to merge.</param>
56 /// <param name="length">The length of the slice to merge.</param>
57 public static void MergeFrom(this IMessage message, byte[] data, int offset, int length) =>
58 MergeFrom(message, data, offset, length, false);
Brian Silverman9c614bc2016-02-15 20:20:02 -050059
60 /// <summary>
61 /// Merges data from the given byte string into an existing message.
62 /// </summary>
63 /// <param name="message">The message to merge the data into.</param>
64 /// <param name="data">The data to merge, which must be protobuf-encoded binary data.</param>
Austin Schuh40c16522018-10-28 20:27:54 -070065 public static void MergeFrom(this IMessage message, ByteString data) =>
66 MergeFrom(message, data, false);
Brian Silverman9c614bc2016-02-15 20:20:02 -050067
68 /// <summary>
69 /// Merges data from the given stream into an existing message.
70 /// </summary>
71 /// <param name="message">The message to merge the data into.</param>
72 /// <param name="input">Stream containing the data to merge, which must be protobuf-encoded binary data.</param>
Austin Schuh40c16522018-10-28 20:27:54 -070073 public static void MergeFrom(this IMessage message, Stream input) =>
74 MergeFrom(message, input, false);
Brian Silverman9c614bc2016-02-15 20:20:02 -050075
76 /// <summary>
77 /// Merges length-delimited data from the given stream into an existing message.
78 /// </summary>
79 /// <remarks>
80 /// The stream is expected to contain a length and then the data. Only the amount of data
81 /// specified by the length will be consumed.
82 /// </remarks>
83 /// <param name="message">The message to merge the data into.</param>
84 /// <param name="input">Stream containing the data to merge, which must be protobuf-encoded binary data.</param>
Austin Schuh40c16522018-10-28 20:27:54 -070085 public static void MergeDelimitedFrom(this IMessage message, Stream input) =>
86 MergeDelimitedFrom(message, input, false);
Brian Silverman9c614bc2016-02-15 20:20:02 -050087
88 /// <summary>
89 /// Converts the given message into a byte array in protobuf encoding.
90 /// </summary>
91 /// <param name="message">The message to convert.</param>
92 /// <returns>The message data as a byte array.</returns>
93 public static byte[] ToByteArray(this IMessage message)
94 {
95 ProtoPreconditions.CheckNotNull(message, "message");
96 byte[] result = new byte[message.CalculateSize()];
97 CodedOutputStream output = new CodedOutputStream(result);
98 message.WriteTo(output);
99 output.CheckNoSpaceLeft();
100 return result;
101 }
102
103 /// <summary>
104 /// Writes the given message data to the given stream in protobuf encoding.
105 /// </summary>
106 /// <param name="message">The message to write to the stream.</param>
107 /// <param name="output">The stream to write to.</param>
108 public static void WriteTo(this IMessage message, Stream output)
109 {
110 ProtoPreconditions.CheckNotNull(message, "message");
111 ProtoPreconditions.CheckNotNull(output, "output");
112 CodedOutputStream codedOutput = new CodedOutputStream(output);
113 message.WriteTo(codedOutput);
114 codedOutput.Flush();
115 }
116
117 /// <summary>
118 /// Writes the length and then data of the given message to a stream.
119 /// </summary>
120 /// <param name="message">The message to write.</param>
121 /// <param name="output">The output stream to write to.</param>
122 public static void WriteDelimitedTo(this IMessage message, Stream output)
123 {
124 ProtoPreconditions.CheckNotNull(message, "message");
125 ProtoPreconditions.CheckNotNull(output, "output");
126 CodedOutputStream codedOutput = new CodedOutputStream(output);
127 codedOutput.WriteRawVarint32((uint)message.CalculateSize());
128 message.WriteTo(codedOutput);
129 codedOutput.Flush();
130 }
131
132 /// <summary>
133 /// Converts the given message into a byte string in protobuf encoding.
134 /// </summary>
135 /// <param name="message">The message to convert.</param>
136 /// <returns>The message data as a byte string.</returns>
137 public static ByteString ToByteString(this IMessage message)
138 {
139 ProtoPreconditions.CheckNotNull(message, "message");
140 return ByteString.AttachBytes(message.ToByteArray());
Austin Schuh40c16522018-10-28 20:27:54 -0700141 }
142
143 // Implementations allowing unknown fields to be discarded.
144 internal static void MergeFrom(this IMessage message, byte[] data, bool discardUnknownFields)
145 {
146 ProtoPreconditions.CheckNotNull(message, "message");
147 ProtoPreconditions.CheckNotNull(data, "data");
148 CodedInputStream input = new CodedInputStream(data);
149 input.DiscardUnknownFields = discardUnknownFields;
150 message.MergeFrom(input);
151 input.CheckReadEndOfStreamTag();
152 }
153
154 internal static void MergeFrom(this IMessage message, byte[] data, int offset, int length, bool discardUnknownFields)
155 {
156 ProtoPreconditions.CheckNotNull(message, "message");
157 ProtoPreconditions.CheckNotNull(data, "data");
158 CodedInputStream input = new CodedInputStream(data, offset, length);
159 input.DiscardUnknownFields = discardUnknownFields;
160 message.MergeFrom(input);
161 input.CheckReadEndOfStreamTag();
162 }
163
164 internal static void MergeFrom(this IMessage message, ByteString data, bool discardUnknownFields)
165 {
166 ProtoPreconditions.CheckNotNull(message, "message");
167 ProtoPreconditions.CheckNotNull(data, "data");
168 CodedInputStream input = data.CreateCodedInput();
169 input.DiscardUnknownFields = discardUnknownFields;
170 message.MergeFrom(input);
171 input.CheckReadEndOfStreamTag();
172 }
173
174 internal static void MergeFrom(this IMessage message, Stream input, bool discardUnknownFields)
175 {
176 ProtoPreconditions.CheckNotNull(message, "message");
177 ProtoPreconditions.CheckNotNull(input, "input");
178 CodedInputStream codedInput = new CodedInputStream(input);
179 codedInput.DiscardUnknownFields = discardUnknownFields;
180 message.MergeFrom(codedInput);
181 codedInput.CheckReadEndOfStreamTag();
182 }
183
184 internal static void MergeDelimitedFrom(this IMessage message, Stream input, bool discardUnknownFields)
185 {
186 ProtoPreconditions.CheckNotNull(message, "message");
187 ProtoPreconditions.CheckNotNull(input, "input");
188 int size = (int) CodedInputStream.ReadRawVarint32(input);
189 Stream limitedStream = new LimitedInputStream(input, size);
190 MergeFrom(message, limitedStream, discardUnknownFields);
191 }
Brian Silverman9c614bc2016-02-15 20:20:02 -0500192 }
193}