Commit 9df2defa authored by Jon Skeet's avatar Jon Skeet

Consume unknown fields when parsing.

This is expected to be the cause of the conformance test failures.
Generated code in next commit.
parent b6defa7c
......@@ -36,6 +36,8 @@ using Google.Protobuf.TestProtos;
using NUnit.Framework;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Google.Protobuf.WellKnownTypes;
namespace Google.Protobuf
{
......@@ -590,5 +592,32 @@ namespace Google.Protobuf
Assert.AreEqual(message, message2);
Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, message2.OneofFieldCase);
}
[Test]
public void IgnoreUnknownFields_RealDataStillRead()
{
var message = SampleMessages.CreateFullTestAllTypes();
var stream = new MemoryStream();
var output = new CodedOutputStream(stream);
var unusedFieldNumber = 23456;
Assert.IsFalse(TestAllTypes.Descriptor.Fields.InDeclarationOrder().Select(x => x.FieldNumber).Contains(unusedFieldNumber));
output.WriteTag(unusedFieldNumber, WireFormat.WireType.LengthDelimited);
output.WriteString("ignore me");
message.WriteTo(output);
output.Flush();
stream.Position = 0;
var parsed = TestAllTypes.Parser.ParseFrom(stream);
Assert.AreEqual(message, parsed);
}
[Test]
public void IgnoreUnknownFields_AllTypes()
{
// Simple way of ensuring we can skip all kinds of fields.
var data = SampleMessages.CreateFullTestAllTypes().ToByteArray();
var empty = Empty.Parser.ParseFrom(data);
Assert.AreEqual(new Empty(), empty);
}
}
}
......@@ -308,6 +308,39 @@ namespace Google.Protobuf
return true;
}
/// <summary>
/// Consumes the data for the field with the tag we've just read.
/// This should be called directly after <see cref="ReadTag"/>, when
/// the caller wishes to skip an unknown field.
/// </summary>
public void ConsumeLastField()
{
if (lastTag == 0)
{
throw new InvalidOperationException("ConsumeLastField cannot be called at the end of a stream");
}
switch (WireFormat.GetTagWireType(lastTag))
{
case WireFormat.WireType.StartGroup:
case WireFormat.WireType.EndGroup:
// TODO: Work out how to skip them instead? See issue 688.
throw new InvalidProtocolBufferException("Group tags not supported by proto3 C# implementation");
case WireFormat.WireType.Fixed32:
ReadFixed32();
break;
case WireFormat.WireType.Fixed64:
ReadFixed64();
break;
case WireFormat.WireType.LengthDelimited:
var length = ReadLength();
SkipRawBytes(length);
break;
case WireFormat.WireType.Varint:
ReadRawVarint32();
break;
}
}
/// <summary>
/// Reads a double field from the stream.
/// </summary>
......
......@@ -428,7 +428,8 @@ void MessageGenerator::GenerateMergingMethods(io::Printer* printer) {
" if (pb::WireFormat.IsEndGroupTag(tag)) {\n"
" return;\n"
" }\n"
" break;\n"); // Note: we're ignoring unknown fields here.
" input.ConsumeLastField();\n" // We're not storing the data, but we still need to consume it.
" break;\n");
for (int i = 0; i < fields_by_number().size(); i++) {
const FieldDescriptor* field = fields_by_number()[i];
internal::WireFormatLite::WireType wt =
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment