public void WriteContext_WritesWithFlushes() { TestAllTypes message = SampleMessages.CreateFullTestAllTypes(); MemoryStream expectedOutput = new MemoryStream(); CodedOutputStream output = new CodedOutputStream(expectedOutput); output.WriteMessage(message); output.Flush(); byte[] expectedBytes1 = expectedOutput.ToArray(); output.WriteMessage(message); output.Flush(); byte[] expectedBytes2 = expectedOutput.ToArray(); var bufferWriter = new TestArrayBufferWriter <byte>(); WriteContext.Initialize(bufferWriter, out WriteContext ctx); ctx.WriteMessage(message); ctx.Flush(); Assert.AreEqual(expectedBytes1, bufferWriter.WrittenSpan.ToArray()); ctx.WriteMessage(message); ctx.Flush(); Assert.AreEqual(expectedBytes2, bufferWriter.WrittenSpan.ToArray()); }
public void LegacyGeneratedCodeThrowsWithIBufferWriter() { // if serialization started using IBufferWriter and we don't have a CodedOutputStream // instance at hand, we cannot fall back to the legacy WriteTo(CodedOutputStream) // method and serializatin will fail. As a consequence, one can only use serialization // to IBufferWriter if all the messages in the parsing tree have their generated // code up to date. var message = new ParseContextEnabledMessageB { A = new LegacyGeneratedCodeMessageA { Bb = new ParseContextEnabledMessageB { OptionalInt32 = 12345 } }, OptionalInt32 = 6789 }; var exception = Assert.Throws <InvalidProtocolBufferException>(() => { WriteContext.Initialize(new TestArrayBufferWriter <byte>(), out WriteContext writeCtx); ((IBufferMessage)message).InternalWriteTo(ref writeCtx); }); Assert.AreEqual($"Message {typeof(LegacyGeneratedCodeMessageA).Name} doesn't provide the generated method that enables WriteContext-based serialization. You might need to regenerate the generated protobuf code.", exception.Message); }
/// <summary> /// Parses the given bytes using WriteRawLittleEndian64() and checks /// that the result matches the given value. /// </summary> private static void AssertWriteLittleEndian64(byte[] data, ulong value) { { var rawOutput = new MemoryStream(); var output = new CodedOutputStream(rawOutput); output.WriteRawLittleEndian64(value); output.Flush(); Assert.AreEqual(data, rawOutput.ToArray()); var bufferWriter = new TestArrayBufferWriter <byte>(); WriteContext.Initialize(bufferWriter, out WriteContext ctx); ctx.WriteFixed64(value); ctx.Flush(); Assert.AreEqual(data, bufferWriter.WrittenSpan.ToArray()); } // Try different block sizes. for (int blockSize = 1; blockSize <= 16; blockSize *= 2) { var rawOutput = new MemoryStream(); var output = new CodedOutputStream(rawOutput, blockSize); output.WriteRawLittleEndian64(value); output.Flush(); Assert.AreEqual(data, rawOutput.ToArray()); var bufferWriter = new TestArrayBufferWriter <byte> { MaxGrowBy = blockSize }; WriteContext.Initialize(bufferWriter, out WriteContext ctx); ctx.WriteFixed64(value); ctx.Flush(); Assert.AreEqual(data, bufferWriter.WrittenSpan.ToArray()); } }
public void WriteTo(ref WriteContext ctx) { foreach (KeyValuePair <int, UnknownField> entry in fields) { entry.Value.WriteTo(entry.Key, ref ctx); } }
internal static void Initialize(ref Span <byte> buffer, out WriteContext ctx) { ctx.buffer = buffer; ctx.state = default; ctx.state.limit = ctx.buffer.Length; ctx.state.position = 0; WriteBufferHelper.InitializeNonRefreshable(out ctx.state.writeBufferHelper); }
internal static void Initialize(IBufferWriter <byte> output, out WriteContext ctx) { ctx.buffer = default; ctx.state = default; WriteBufferHelper.Initialize(output, out ctx.state.writeBufferHelper, out ctx.buffer); ctx.state.limit = ctx.buffer.Length; ctx.state.position = 0; }
internal static void Initialize(CodedOutputStream output, out WriteContext ctx) { ctx.buffer = new Span <byte>(output.InternalBuffer); // ideally we would use a reference to the original state, but that doesn't seem possible // so we just copy the struct that holds the state. We will need to later store the state back // into CodedOutputStream if we want to keep it usable. ctx.state = output.InternalState; }
public static void WriteTo(this IMessage message, IBufferWriter <byte> output) { ProtoPreconditions.CheckNotNull(message, nameof(message)); ProtoPreconditions.CheckNotNull(output, nameof(output)); WriteContext.Initialize(output, out WriteContext ctx); WritingPrimitivesMessages.WriteRawMessage(ref ctx, message); ctx.Flush(); }
public void WriteTo(ref WriteContext ctx) { ctx.WriteTag(codec.Tag); codec.ValueWriter(ref ctx, field); if (codec.EndTag != 0) { ctx.WriteTag(codec.EndTag); } }
/// <summary> /// Serializes the set and writes it to <paramref name="output"/>. /// </summary> public void WriteTo(CodedOutputStream output) { WriteContext.Initialize(output, out WriteContext ctx); try { WriteTo(ref ctx); } finally { ctx.CopyStateTo(output); } }
/// <summary> /// Serializes the field, including the field number, and writes it to /// <paramref name="output"/> /// </summary> /// <param name="fieldNumber">The unknown field number.</param> /// <param name="output">The write context to write to.</param> internal void WriteTo(int fieldNumber, ref WriteContext output) { if (varintList != null) { foreach (ulong value in varintList) { output.WriteTag(fieldNumber, WireFormat.WireType.Varint); output.WriteUInt64(value); } } if (fixed32List != null) { foreach (uint value in fixed32List) { output.WriteTag(fieldNumber, WireFormat.WireType.Fixed32); output.WriteFixed32(value); } } if (fixed64List != null) { foreach (ulong value in fixed64List) { output.WriteTag(fieldNumber, WireFormat.WireType.Fixed64); output.WriteFixed64(value); } } if (lengthDelimitedList != null) { foreach (ByteString value in lengthDelimitedList) { output.WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited); output.WriteBytes(value); } } if (groupList != null) { foreach (UnknownFieldSet value in groupList) { output.WriteTag(fieldNumber, WireFormat.WireType.StartGroup); value.WriteTo(ref output); output.WriteTag(fieldNumber, WireFormat.WireType.EndGroup); } } }
void pb.IBufferMessage.InternalWriteTo(ref pb.WriteContext output) { if (ClientId.Length != 0) { output.WriteRawTag(10); output.WriteString(ClientId); } if (MessageId.Length != 0) { output.WriteRawTag(18); output.WriteString(MessageId); } if (Type != MessageType.Undefined) { output.WriteRawTag(24); output.WriteEnum((int)Type); } if (time_ != null) { output.WriteRawTag(34); output.WriteMessage(Time); } if (Status != MessageStatus.Undefined) { output.WriteRawTag(40); output.WriteEnum((int)Status); } if (Payload.Length != 0) { output.WriteRawTag(50); output.WriteBytes(Payload); } if (Response != ResponseType.Undefined) { output.WriteRawTag(56); output.WriteEnum((int)Response); } if (_unknownFields != null) { _unknownFields.WriteTo(ref output); } }
public void TestDefaultValue() { // WriteTagAndValue ignores default values var stream = new MemoryStream(); CodedOutputStream codedOutput; #if !NET35 codedOutput = new CodedOutputStream(stream); codec.WriteTagAndValue(codedOutput, codec.DefaultValue); codedOutput.Flush(); Assert.AreEqual(0, stream.Position); Assert.AreEqual(0, codec.CalculateSizeWithTag(codec.DefaultValue)); if (typeof(T).GetTypeInfo().IsValueType) { Assert.AreEqual(default(T), codec.DefaultValue); } #endif // The plain ValueWriter/ValueReader delegates don't. if (codec.DefaultValue != null) // This part isn't appropriate for message types. { codedOutput = new CodedOutputStream(stream); WriteContext.Initialize(codedOutput, out WriteContext ctx); try { // only write the value using the codec codec.ValueWriter(ref ctx, codec.DefaultValue); } finally { ctx.CopyStateTo(codedOutput); } codedOutput.Flush(); Assert.AreNotEqual(0, stream.Position); Assert.AreEqual(stream.Position, codec.ValueSizeCalculator(codec.DefaultValue)); stream.Position = 0; var codedInput = new CodedInputStream(stream); Assert.AreEqual(codec.DefaultValue, codec.Read(codedInput)); } }
public static void WriteRawMessage(ref WriteContext ctx, IMessage message) { if (message is IBufferMessage bufferMessage) { bufferMessage.InternalWriteTo(ref ctx); } else { // If we reached here, it means we've ran into a nested message with older generated code // which doesn't provide the InternalWriteTo method that takes a WriteContext. // With a slight performance overhead, we can still serialize this message just fine, // but we need to find the original CodedOutputStream instance that initiated this // serialization process and make sure its internal state is up to date. // Note that this performance overhead is not very high (basically copying contents of a struct) // and it will only be incurred in case the application mixes older and newer generated code. // Regenerating the code from .proto files will remove this overhead because it will // generate the InternalWriteTo method we need. if (ctx.state.CodedOutputStream == null) { // This can only happen when the serialization started without providing a CodedOutputStream instance // (e.g. WriteContext was created directly from a IBufferWriter). // That also means that one of the new parsing APIs was used at the top level // and in such case it is reasonable to require that all the nested message provide // up-to-date generated code with WriteContext support (and fail otherwise). throw new InvalidProtocolBufferException($"Message {message.GetType().Name} doesn't provide the generated method that enables WriteContext-based serialization. You might need to regenerate the generated protobuf code."); } ctx.CopyStateTo(ctx.state.CodedOutputStream); try { // fallback parse using the CodedOutputStream that started current serialization tree message.WriteTo(ctx.state.CodedOutputStream); } finally { ctx.LoadStateFrom(ctx.state.CodedOutputStream); } } }
public void TestRoundTripRaw() { var stream = new MemoryStream(); var codedOutput = new CodedOutputStream(stream); WriteContext.Initialize(codedOutput, out WriteContext ctx); try { // only write the value using the codec codec.ValueWriter(ref ctx, sampleValue); } finally { ctx.CopyStateTo(codedOutput); } codedOutput.Flush(); stream.Position = 0; var codedInput = new CodedInputStream(stream); Assert.AreEqual(sampleValue, codec.Read(codedInput)); Assert.IsTrue(codedInput.IsAtEnd); }
public static void WriteMessage(ref WriteContext ctx, IMessage value) { WritingPrimitives.WriteLength(ref ctx.buffer, ref ctx.state, value.CalculateSize()); WriteRawMessage(ref ctx, value); }
internal static void Initialize(ref Span <byte> buffer, ref WriterInternalState state, out WriteContext ctx) { ctx.buffer = buffer; ctx.state = state; }
public void WriteTo(ref WriteContext ctx) { field.WriteTo(ref ctx, codec); }
internal static void Write <T>(ref WriteContext ctx, T value, FieldCodec <T> codec) { ctx.WriteLength(codec.CalculateSizeWithTag(value)); codec.WriteTagAndValue(ref ctx, value); }
/// <summary> /// Writes the given value using WriteRawVarint32() and WriteRawVarint64() and /// checks that the result matches the given bytes /// </summary> private static void AssertWriteVarint(byte[] data, ulong value) { // Only do 32-bit write if the value fits in 32 bits. if ((value >> 32) == 0) { // CodedOutputStream MemoryStream rawOutput = new MemoryStream(); CodedOutputStream output = new CodedOutputStream(rawOutput); output.WriteRawVarint32((uint)value); output.Flush(); Assert.AreEqual(data, rawOutput.ToArray()); // IBufferWriter var bufferWriter = new TestArrayBufferWriter <byte>(); WriteContext.Initialize(bufferWriter, out WriteContext ctx); ctx.WriteUInt32((uint)value); ctx.Flush(); Assert.AreEqual(data, bufferWriter.WrittenSpan.ToArray()); // Also try computing size. Assert.AreEqual(data.Length, CodedOutputStream.ComputeRawVarint32Size((uint)value)); } { // CodedOutputStream MemoryStream rawOutput = new MemoryStream(); CodedOutputStream output = new CodedOutputStream(rawOutput); output.WriteRawVarint64(value); output.Flush(); Assert.AreEqual(data, rawOutput.ToArray()); // IBufferWriter var bufferWriter = new TestArrayBufferWriter <byte>(); WriteContext.Initialize(bufferWriter, out WriteContext ctx); ctx.WriteUInt64(value); ctx.Flush(); Assert.AreEqual(data, bufferWriter.WrittenSpan.ToArray()); // Also try computing size. Assert.AreEqual(data.Length, CodedOutputStream.ComputeRawVarint64Size(value)); } // Try different buffer sizes. for (int bufferSize = 1; bufferSize <= 16; bufferSize *= 2) { // Only do 32-bit write if the value fits in 32 bits. if ((value >> 32) == 0) { MemoryStream rawOutput = new MemoryStream(); CodedOutputStream output = new CodedOutputStream(rawOutput, bufferSize); output.WriteRawVarint32((uint)value); output.Flush(); Assert.AreEqual(data, rawOutput.ToArray()); var bufferWriter = new TestArrayBufferWriter <byte> { MaxGrowBy = bufferSize }; WriteContext.Initialize(bufferWriter, out WriteContext ctx); ctx.WriteUInt32((uint)value); ctx.Flush(); Assert.AreEqual(data, bufferWriter.WrittenSpan.ToArray()); } { MemoryStream rawOutput = new MemoryStream(); CodedOutputStream output = new CodedOutputStream(rawOutput, bufferSize); output.WriteRawVarint64(value); output.Flush(); Assert.AreEqual(data, rawOutput.ToArray()); var bufferWriter = new TestArrayBufferWriter <byte> { MaxGrowBy = bufferSize }; WriteContext.Initialize(bufferWriter, out WriteContext ctx); ctx.WriteUInt64(value); ctx.Flush(); Assert.AreEqual(data, bufferWriter.WrittenSpan.ToArray()); } } }
public static void WriteGroup(ref WriteContext ctx, IMessage value) { WriteRawMessage(ref ctx, value); }