• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #region Copyright notice and license
2 // Protocol Buffers - Google's data interchange format
3 // Copyright 2008 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 
33 using System;
34 using System.Buffers;
35 using System.Buffers.Binary;
36 using System.Collections.Generic;
37 using System.IO;
38 using System.Runtime.CompilerServices;
39 using System.Runtime.InteropServices;
40 using System.Security;
41 using System.Text;
42 using Google.Protobuf.Collections;
43 
44 namespace Google.Protobuf
45 {
46     /// <summary>
47     /// An opaque struct that represents the current serialization state and is passed along
48     /// as the serialization proceeds.
49     /// All the public methods are intended to be invoked only by the generated code,
50     /// users should never invoke them directly.
51     /// </summary>
52     [SecuritySafeCritical]
53     public ref struct WriteContext
54     {
55         internal Span<byte> buffer;
56         internal WriterInternalState state;
57 
58         [MethodImpl(MethodImplOptions.AggressiveInlining)]
InitializeGoogle.Protobuf.WriteContext59         internal static void Initialize(ref Span<byte> buffer, ref WriterInternalState state, out WriteContext ctx)
60         {
61             ctx.buffer = buffer;
62             ctx.state = state;
63         }
64 
65         /// <summary>
66         /// Creates a WriteContext instance from CodedOutputStream.
67         /// WARNING: internally this copies the CodedOutputStream's state, so after done with the WriteContext,
68         /// the CodedOutputStream's state needs to be updated.
69         /// </summary>
70         [MethodImpl(MethodImplOptions.AggressiveInlining)]
InitializeGoogle.Protobuf.WriteContext71         internal static void Initialize(CodedOutputStream output, out WriteContext ctx)
72         {
73             ctx.buffer = new Span<byte>(output.InternalBuffer);
74             // ideally we would use a reference to the original state, but that doesn't seem possible
75             // so we just copy the struct that holds the state. We will need to later store the state back
76             // into CodedOutputStream if we want to keep it usable.
77             ctx.state = output.InternalState;
78         }
79 
80         [MethodImpl(MethodImplOptions.AggressiveInlining)]
InitializeGoogle.Protobuf.WriteContext81         internal static void Initialize(IBufferWriter<byte> output, out WriteContext ctx)
82         {
83             ctx.buffer = default;
84             ctx.state = default;
85             WriteBufferHelper.Initialize(output, out ctx.state.writeBufferHelper, out ctx.buffer);
86             ctx.state.limit = ctx.buffer.Length;
87             ctx.state.position = 0;
88         }
89 
90         [MethodImpl(MethodImplOptions.AggressiveInlining)]
InitializeGoogle.Protobuf.WriteContext91         internal static void Initialize(ref Span<byte> buffer, out WriteContext ctx)
92         {
93             ctx.buffer = buffer;
94             ctx.state = default;
95             ctx.state.limit = ctx.buffer.Length;
96             ctx.state.position = 0;
97             WriteBufferHelper.InitializeNonRefreshable(out ctx.state.writeBufferHelper);
98         }
99 
100         /// <summary>
101         /// Writes a double field value, without a tag.
102         /// </summary>
103         /// <param name="value">The value to write</param>
WriteDoubleGoogle.Protobuf.WriteContext104         public void WriteDouble(double value)
105         {
106             WritingPrimitives.WriteDouble(ref buffer, ref state, value);
107         }
108 
109         /// <summary>
110         /// Writes a float field value, without a tag.
111         /// </summary>
112         /// <param name="value">The value to write</param>
WriteFloatGoogle.Protobuf.WriteContext113         public void WriteFloat(float value)
114         {
115             WritingPrimitives.WriteFloat(ref buffer, ref state, value);
116         }
117 
118         /// <summary>
119         /// Writes a uint64 field value, without a tag.
120         /// </summary>
121         /// <param name="value">The value to write</param>
WriteUInt64Google.Protobuf.WriteContext122         public void WriteUInt64(ulong value)
123         {
124             WritingPrimitives.WriteUInt64(ref buffer, ref state, value);
125         }
126 
127         /// <summary>
128         /// Writes an int64 field value, without a tag.
129         /// </summary>
130         /// <param name="value">The value to write</param>
WriteInt64Google.Protobuf.WriteContext131         public void WriteInt64(long value)
132         {
133             WritingPrimitives.WriteInt64(ref buffer, ref state, value);
134         }
135 
136         /// <summary>
137         /// Writes an int32 field value, without a tag.
138         /// </summary>
139         /// <param name="value">The value to write</param>
WriteInt32Google.Protobuf.WriteContext140         public void WriteInt32(int value)
141         {
142             WritingPrimitives.WriteInt32(ref buffer, ref state, value);
143         }
144 
145         /// <summary>
146         /// Writes a fixed64 field value, without a tag.
147         /// </summary>
148         /// <param name="value">The value to write</param>
WriteFixed64Google.Protobuf.WriteContext149         public void WriteFixed64(ulong value)
150         {
151             WritingPrimitives.WriteFixed64(ref buffer, ref state, value);
152         }
153 
154         /// <summary>
155         /// Writes a fixed32 field value, without a tag.
156         /// </summary>
157         /// <param name="value">The value to write</param>
WriteFixed32Google.Protobuf.WriteContext158         public void WriteFixed32(uint value)
159         {
160             WritingPrimitives.WriteFixed32(ref buffer, ref state, value);
161         }
162 
163         /// <summary>
164         /// Writes a bool field value, without a tag.
165         /// </summary>
166         /// <param name="value">The value to write</param>
WriteBoolGoogle.Protobuf.WriteContext167         public void WriteBool(bool value)
168         {
169             WritingPrimitives.WriteBool(ref buffer, ref state, value);
170         }
171 
172         /// <summary>
173         /// Writes a string field value, without a tag.
174         /// The data is length-prefixed.
175         /// </summary>
176         /// <param name="value">The value to write</param>
WriteStringGoogle.Protobuf.WriteContext177         public void WriteString(string value)
178         {
179             WritingPrimitives.WriteString(ref buffer, ref state, value);
180         }
181 
182         /// <summary>
183         /// Writes a message, without a tag.
184         /// The data is length-prefixed.
185         /// </summary>
186         /// <param name="value">The value to write</param>
WriteMessageGoogle.Protobuf.WriteContext187         public void WriteMessage(IMessage value)
188         {
189             WritingPrimitivesMessages.WriteMessage(ref this, value);
190         }
191 
192         /// <summary>
193         /// Writes a group, without a tag, to the stream.
194         /// </summary>
195         /// <param name="value">The value to write</param>
WriteGroupGoogle.Protobuf.WriteContext196         public void WriteGroup(IMessage value)
197         {
198             WritingPrimitivesMessages.WriteGroup(ref this, value);
199         }
200 
201         /// <summary>
202         /// Write a byte string, without a tag, to the stream.
203         /// The data is length-prefixed.
204         /// </summary>
205         /// <param name="value">The value to write</param>
WriteBytesGoogle.Protobuf.WriteContext206         public void WriteBytes(ByteString value)
207         {
208             WritingPrimitives.WriteBytes(ref buffer, ref state, value);
209         }
210 
211         /// <summary>
212         /// Writes a uint32 value, without a tag.
213         /// </summary>
214         /// <param name="value">The value to write</param>
WriteUInt32Google.Protobuf.WriteContext215         public void WriteUInt32(uint value)
216         {
217             WritingPrimitives.WriteUInt32(ref buffer, ref state, value);
218         }
219 
220         /// <summary>
221         /// Writes an enum value, without a tag.
222         /// </summary>
223         /// <param name="value">The value to write</param>
WriteEnumGoogle.Protobuf.WriteContext224         public void WriteEnum(int value)
225         {
226             WritingPrimitives.WriteEnum(ref buffer, ref state, value);
227         }
228 
229         /// <summary>
230         /// Writes an sfixed32 value, without a tag.
231         /// </summary>
232         /// <param name="value">The value to write.</param>
WriteSFixed32Google.Protobuf.WriteContext233         public void WriteSFixed32(int value)
234         {
235             WritingPrimitives.WriteSFixed32(ref buffer, ref state, value);
236         }
237 
238         /// <summary>
239         /// Writes an sfixed64 value, without a tag.
240         /// </summary>
241         /// <param name="value">The value to write</param>
WriteSFixed64Google.Protobuf.WriteContext242         public void WriteSFixed64(long value)
243         {
244             WritingPrimitives.WriteSFixed64(ref buffer, ref state, value);
245         }
246 
247         /// <summary>
248         /// Writes an sint32 value, without a tag.
249         /// </summary>
250         /// <param name="value">The value to write</param>
WriteSInt32Google.Protobuf.WriteContext251         public void WriteSInt32(int value)
252         {
253             WritingPrimitives.WriteSInt32(ref buffer, ref state, value);
254         }
255 
256         /// <summary>
257         /// Writes an sint64 value, without a tag.
258         /// </summary>
259         /// <param name="value">The value to write</param>
WriteSInt64Google.Protobuf.WriteContext260         public void WriteSInt64(long value)
261         {
262             WritingPrimitives.WriteSInt64(ref buffer, ref state, value);
263         }
264 
265         /// <summary>
266         /// Writes a length (in bytes) for length-delimited data.
267         /// </summary>
268         /// <remarks>
269         /// This method simply writes a rawint, but exists for clarity in calling code.
270         /// </remarks>
271         /// <param name="length">Length value, in bytes.</param>
WriteLengthGoogle.Protobuf.WriteContext272         public void WriteLength(int length)
273         {
274             WritingPrimitives.WriteLength(ref buffer, ref state, length);
275         }
276 
277         /// <summary>
278         /// Encodes and writes a tag.
279         /// </summary>
280         /// <param name="fieldNumber">The number of the field to write the tag for</param>
281         /// <param name="type">The wire format type of the tag to write</param>
WriteTagGoogle.Protobuf.WriteContext282         public void WriteTag(int fieldNumber, WireFormat.WireType type)
283         {
284             WritingPrimitives.WriteTag(ref buffer, ref state, fieldNumber, type);
285         }
286 
287         /// <summary>
288         /// Writes an already-encoded tag.
289         /// </summary>
290         /// <param name="tag">The encoded tag</param>
WriteTagGoogle.Protobuf.WriteContext291         public void WriteTag(uint tag)
292         {
293             WritingPrimitives.WriteTag(ref buffer, ref state, tag);
294         }
295 
296         /// <summary>
297         /// Writes the given single-byte tag.
298         /// </summary>
299         /// <param name="b1">The encoded tag</param>
WriteRawTagGoogle.Protobuf.WriteContext300         public void WriteRawTag(byte b1)
301         {
302             WritingPrimitives.WriteRawTag(ref buffer, ref state, b1);
303         }
304 
305         /// <summary>
306         /// Writes the given two-byte tag.
307         /// </summary>
308         /// <param name="b1">The first byte of the encoded tag</param>
309         /// <param name="b2">The second byte of the encoded tag</param>
WriteRawTagGoogle.Protobuf.WriteContext310         public void WriteRawTag(byte b1, byte b2)
311         {
312             WritingPrimitives.WriteRawTag(ref buffer, ref state, b1, b2);
313         }
314 
315         /// <summary>
316         /// Writes the given three-byte tag.
317         /// </summary>
318         /// <param name="b1">The first byte of the encoded tag</param>
319         /// <param name="b2">The second byte of the encoded tag</param>
320         /// <param name="b3">The third byte of the encoded tag</param>
WriteRawTagGoogle.Protobuf.WriteContext321         public void WriteRawTag(byte b1, byte b2, byte b3)
322         {
323             WritingPrimitives.WriteRawTag(ref buffer, ref state, b1, b2, b3);
324         }
325 
326         /// <summary>
327         /// Writes the given four-byte tag.
328         /// </summary>
329         /// <param name="b1">The first byte of the encoded tag</param>
330         /// <param name="b2">The second byte of the encoded tag</param>
331         /// <param name="b3">The third byte of the encoded tag</param>
332         /// <param name="b4">The fourth byte of the encoded tag</param>
WriteRawTagGoogle.Protobuf.WriteContext333         public void WriteRawTag(byte b1, byte b2, byte b3, byte b4)
334         {
335             WritingPrimitives.WriteRawTag(ref buffer, ref state, b1, b2, b3, b4);
336         }
337 
338         /// <summary>
339         /// Writes the given five-byte tag.
340         /// </summary>
341         /// <param name="b1">The first byte of the encoded tag</param>
342         /// <param name="b2">The second byte of the encoded tag</param>
343         /// <param name="b3">The third byte of the encoded tag</param>
344         /// <param name="b4">The fourth byte of the encoded tag</param>
345         /// <param name="b5">The fifth byte of the encoded tag</param>
WriteRawTagGoogle.Protobuf.WriteContext346         public void WriteRawTag(byte b1, byte b2, byte b3, byte b4, byte b5)
347         {
348             WritingPrimitives.WriteRawTag(ref buffer, ref state, b1, b2, b3, b4, b5);
349         }
350 
FlushGoogle.Protobuf.WriteContext351         internal void Flush()
352         {
353             WriteBufferHelper.Flush(ref buffer, ref state);
354         }
355 
CheckNoSpaceLeftGoogle.Protobuf.WriteContext356         internal void CheckNoSpaceLeft()
357         {
358             WriteBufferHelper.CheckNoSpaceLeft(ref state);
359         }
360 
CopyStateToGoogle.Protobuf.WriteContext361         internal void CopyStateTo(CodedOutputStream output)
362         {
363             output.InternalState = state;
364         }
365 
LoadStateFromGoogle.Protobuf.WriteContext366         internal void LoadStateFrom(CodedOutputStream output)
367         {
368             state = output.InternalState;
369         }
370     }
371 }