Commit 2b868846 authored by csharptest's avatar csharptest Committed by rogerk

Added the XmlFormatWriter/Reader

parent b00ea13e
......@@ -6,8 +6,6 @@ namespace Google.ProtocolBuffers.CompatTests
[TestFixture]
public class BinaryCompatibilityTests : CompatibilityTests
{
protected override string TestName { get { return "binary"; } }
protected override object SerializeMessage<TMessage, TBuilder>(TMessage message)
{
byte[] bresult = message.ToByteArray();
......
......@@ -6,7 +6,6 @@ namespace Google.ProtocolBuffers.CompatTests
{
public abstract class CompatibilityTests
{
protected abstract string TestName { get; }
protected abstract object SerializeMessage<TMessage, TBuilder>(TMessage message)
where TMessage : IMessageLite<TMessage, TBuilder>
where TBuilder : IBuilderLite<TMessage, TBuilder>;
......
......@@ -7,8 +7,6 @@ namespace Google.ProtocolBuffers.CompatTests
[TestFixture]
public class TextCompatibilityTests : CompatibilityTests
{
protected override string TestName { get { return "text"; } }
protected override object SerializeMessage<TMessage, TBuilder>(TMessage message)
{
StringWriter text = new StringWriter();
......
using System.IO;
using Google.ProtocolBuffers.Serialization;
using NUnit.Framework;
namespace Google.ProtocolBuffers.CompatTests
{
[TestFixture]
public class XmlCompatibilityTests : CompatibilityTests
{
protected override object SerializeMessage<TMessage, TBuilder>(TMessage message)
{
StringWriter text = new StringWriter();
XmlFormatWriter writer = new XmlFormatWriter(text);
writer.WriteMessage("root", message);
return text.ToString();
}
protected override TBuilder DeerializeMessage<TMessage, TBuilder>(object message, TBuilder builder, ExtensionRegistry registry)
{
XmlFormatReader reader = new XmlFormatReader((string)message);
return reader.Merge("root", builder, registry);
}
}
}
\ No newline at end of file
......@@ -83,6 +83,7 @@
<DependentUpon>TestResources.resx</DependentUpon>
</Compile>
<Compile Include="CompatTests\TextCompatibilityTests.cs" />
<Compile Include="CompatTests\XmlCompatibilityTests.cs" />
<Compile Include="CSharpOptionsTest.cs" />
<Compile Include="DescriptorsTest.cs" />
<Compile Include="Descriptors\MessageDescriptorTest.cs" />
......@@ -114,6 +115,7 @@
<Compile Include="TestProtos\UnitTestXmlSerializerTestProtoFile.cs" />
<Compile Include="TestRpcGenerator.cs" />
<Compile Include="TestUtil.cs" />
<Compile Include="TestWriterFormatXml.cs" />
<Compile Include="TextFormatTest.cs" />
<Compile Include="UnknownFieldSetTest.cs" />
<Compile Include="WireFormatTest.cs" />
......
This diff is collapsed.
......@@ -127,6 +127,36 @@ namespace Google.ProtocolBuffers
#endregion
#region Writing of unknown fields
[Obsolete]
public void WriteUnknownGroup(int fieldNumber, IMessageLite value)
{
WriteTag(fieldNumber, WireFormat.WireType.StartGroup);
value.WriteTo(this);
WriteTag(fieldNumber, WireFormat.WireType.EndGroup);
}
public void WriteUnknownBytes(int fieldNumber, ByteString value)
{
WriteBytes(fieldNumber, null /*not used*/, value);
}
[CLSCompliant(false)]
public void WriteUnknownField(int fieldNumber, WireFormat.WireType wireType, ulong value)
{
if(wireType == WireFormat.WireType.Varint)
WriteUInt64(fieldNumber, null /*not used*/, value);
else if (wireType == WireFormat.WireType.Fixed32)
WriteFixed32(fieldNumber, null /*not used*/, (uint)value);
else if (wireType == WireFormat.WireType.Fixed64)
WriteFixed64(fieldNumber, null /*not used*/, value);
else
throw InvalidProtocolBufferException.InvalidWireType();
}
#endregion
#region Writing of tags and fields
public void WriteField(FieldType fieldType, int fieldNumber, string fieldName, object value)
......@@ -308,14 +338,6 @@ namespace Google.ProtocolBuffers
WriteTag(fieldNumber, WireFormat.WireType.EndGroup);
}
[Obsolete]
public void WriteUnknownGroup(int fieldNumber, string fieldName, IMessageLite value)
{
WriteTag(fieldNumber, WireFormat.WireType.StartGroup);
value.WriteTo(this);
WriteTag(fieldNumber, WireFormat.WireType.EndGroup);
}
public void WriteMessage(int fieldNumber, string fieldName, IMessageLite value)
{
WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
......
......@@ -12,7 +12,11 @@ namespace Google.ProtocolBuffers
void Flush();
[Obsolete]
void WriteUnknownGroup(int fieldNumber, string fieldName, IMessageLite value);
void WriteUnknownGroup(int fieldNumber, IMessageLite value);
void WriteUnknownBytes(int fieldNumber, ByteString value);
[CLSCompliant(false)]
void WriteUnknownField(int fieldNumber, WireFormat.WireType wireType, ulong value);
void WriteMessageSetExtension(int fieldNumber, string fieldName, IMessageLite value);
void WriteMessageSetExtension(int fieldNumber, string fieldName, ByteString value);
......
......@@ -180,6 +180,14 @@
<Compile Include="NameHelpers.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RpcUtil.cs" />
<Compile Include="Serialization\AbstractReader.cs" />
<Compile Include="Serialization\AbstractTextReader.cs" />
<Compile Include="Serialization\AbstractTextWriter.cs" />
<Compile Include="Serialization\AbstractWriter.cs" />
<Compile Include="Serialization\XmlFormatReader.cs" />
<Compile Include="Serialization\XmlFormatWriter.cs" />
<Compile Include="Serialization\XmlReaderOptions.cs" />
<Compile Include="Serialization\XmlWriterOptions.cs" />
<Compile Include="SilverlightCompatibility.cs" />
<Compile Include="SortedList.cs" />
<Compile Include="TextFormat.cs" />
......
This diff is collapsed.
using System;
using System.Globalization;
using System.Xml;
namespace Google.ProtocolBuffers.Serialization
{
/// <summary>
/// Provides a base class for text-parsing readers
/// </summary>
public abstract class AbstractTextReader : AbstractReader
{
/// <summary>
/// Reads a typed field as a string
/// </summary>
protected abstract bool ReadAsText(ref string textValue, Type type);
/// <summary>
/// Returns true if it was able to read a String from the input
/// </summary>
protected override bool Read(ref string value)
{
string text = null;
if (ReadAsText(ref text, typeof(string)))
{
value = text;
return true;
}
return false;
}
/// <summary>
/// Returns true if it was able to read a Boolean from the input
/// </summary>
protected override bool Read(ref bool value)
{
string text = null;
if (ReadAsText(ref text, typeof(bool)))
{
value = XmlConvert.ToBoolean(text);
return true;
}
return false;
}
/// <summary>
/// Returns true if it was able to read a Int32 from the input
/// </summary>
protected override bool Read(ref int value)
{
string text = null;
if (ReadAsText(ref text, typeof(int)))
{
value = XmlConvert.ToInt32(text);
return true;
}
return false;
}
/// <summary>
/// Returns true if it was able to read a UInt32 from the input
/// </summary>
[CLSCompliant(false)]
protected override bool Read(ref uint value)
{
string text = null;
if (ReadAsText(ref text, typeof(uint)))
{
value = XmlConvert.ToUInt32(text);
return true;
}
return false;
}
/// <summary>
/// Returns true if it was able to read a Int64 from the input
/// </summary>
protected override bool Read(ref long value)
{
string text = null;
if (ReadAsText(ref text, typeof(long)))
{
value = XmlConvert.ToInt64(text);
return true;
}
return false;
}
/// <summary>
/// Returns true if it was able to read a UInt64 from the input
/// </summary>
[CLSCompliant(false)]
protected override bool Read(ref ulong value)
{
string text = null;
if (ReadAsText(ref text, typeof(ulong)))
{
value = XmlConvert.ToUInt64(text);
return true;
}
return false;
}
/// <summary>
/// Returns true if it was able to read a Single from the input
/// </summary>
protected override bool Read(ref float value)
{
string text = null;
if (ReadAsText(ref text, typeof(float)))
{
value = XmlConvert.ToSingle(text);
return true;
}
return false;
}
/// <summary>
/// Returns true if it was able to read a Double from the input
/// </summary>
protected override bool Read(ref double value)
{
string text = null;
if (ReadAsText(ref text, typeof(double)))
{
value = XmlConvert.ToDouble(text);
return true;
}
return false;
}
/// <summary>
/// Provides decoding of bytes read from the input stream
/// </summary>
protected virtual ByteString DecodeBytes(string bytes) { return ByteString.FromBase64(bytes); }
/// <summary>
/// Returns true if it was able to read a ByteString from the input
/// </summary>
protected override bool Read(ref ByteString value)
{
string text = null;
if (ReadAsText(ref text, typeof(ByteString)))
{
value = DecodeBytes(text);
return true;
}
return false;
}
/// <summary>
/// returns true if it was able to read a single value into the value reference. The value
/// stored may be of type System.String, System.Int32, or an IEnumLite from the IEnumLiteMap.
/// </summary>
protected override bool ReadEnum(ref object value)
{
string text = null;
if (ReadAsText(ref text, typeof(Enum)))
{
int number;
if (int.TryParse(text, NumberStyles.Integer, CultureInfo.InvariantCulture, out number))
{
value = number;
return true;
}
value = text;
return true;
}
return false;
}
}
}
\ No newline at end of file
using System;
using System.Xml;
namespace Google.ProtocolBuffers.Serialization
{
/// <summary>
/// Provides a base class for text writers
/// </summary>
public abstract class AbstractTextWriter : AbstractWriter
{
/// <summary>
/// Encodes raw bytes to be written to the stream
/// </summary>
protected virtual string EncodeBytes(ByteString bytes) { return bytes.ToBase64(); }
/// <summary>
/// Writes a typed field as a text value
/// </summary>
protected abstract void WriteAsText(string field, string textValue, object typedValue);
/// <summary>
/// Writes a String value
/// </summary>
protected override void Write(string field, string value) { WriteAsText(field, value, value); }
/// <summary>
/// Writes a Boolean value
/// </summary>
protected override void Write(string field, bool value) { WriteAsText(field, XmlConvert.ToString(value), value); }
/// <summary>
/// Writes a Int32 value
/// </summary>
protected override void Write(string field, int value) { WriteAsText(field, XmlConvert.ToString(value), value); }
/// <summary>
/// Writes a UInt32 value
/// </summary>
[CLSCompliant(false)]
protected override void Write(string field, uint value) { WriteAsText(field, XmlConvert.ToString(value), value); }
/// <summary>
/// Writes a Int64 value
/// </summary>
protected override void Write(string field, long value) { WriteAsText(field, XmlConvert.ToString(value), value); }
/// <summary>
/// Writes a UInt64 value
/// </summary>
[CLSCompliant(false)]
protected override void Write(string field, ulong value) { WriteAsText(field, XmlConvert.ToString(value), value); }
/// <summary>
/// Writes a Single value
/// </summary>
protected override void Write(string field, float value) { WriteAsText(field, XmlConvert.ToString(value), value); }
/// <summary>
/// Writes a Double value
/// </summary>
protected override void Write(string field, double value) { WriteAsText(field, XmlConvert.ToString(value), value); }
/// <summary>
/// Writes a set of bytes
/// </summary>
protected override void Write(string field, ByteString value) { WriteAsText(field, EncodeBytes(value), value); }
/// <summary>
/// Writes a System.Enum by the numeric and textual value
/// </summary>
protected override void WriteEnum(string field, int number, string name) { WriteAsText(field, name, number); }
}
}
\ No newline at end of file
This diff is collapsed.
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers.Serialization
{
/// <summary>
/// Parses a proto buffer from an XML document or fragment. .NET 3.5 users may also
/// use this class to process Json by setting the options to support Json and providing
/// an XmlReader obtained from <see cref="System.Runtime.Serialization.Json.JsonReaderWriterFactory"/>.
/// </summary>
public class XmlFormatReader : AbstractTextReader
{
public const string DefaultRootElementName = XmlFormatWriter.DefaultRootElementName;
private readonly XmlReader _input;
private string _rootElementName;
static XmlReaderSettings DefaultSettings
{
get { return new XmlReaderSettings() { CheckCharacters=false, IgnoreComments=true, IgnoreProcessingInstructions = true }; }
}
/// <summary>
/// Constructs the XmlFormatReader using the stream provided as the xml
/// </summary>
public XmlFormatReader(Stream input) : this(XmlReader.Create(input, DefaultSettings)) { }
/// <summary>
/// Constructs the XmlFormatReader using the string provided as the xml to be read
/// </summary>
public XmlFormatReader(String input) : this(XmlReader.Create(new StringReader(input))) { }
/// <summary>
/// Constructs the XmlFormatReader using the xml in the TextReader
/// </summary>
public XmlFormatReader(TextReader input) : this(XmlReader.Create(input)) { }
/// <summary>
/// Constructs the XmlFormatReader with the XmlReader
/// </summary>
public XmlFormatReader(XmlReader input) : this(input, XmlReaderOptions.None) { }
/// <summary>
/// Constructs the XmlFormatReader with the XmlReader and options
/// </summary>
public XmlFormatReader(XmlReader input, XmlReaderOptions options)
{
_input = input;
_rootElementName = DefaultRootElementName;
Options = options;
}
/// <summary>
/// Gets or sets the options to use when reading the xml
/// </summary>
public XmlReaderOptions Options { get; set; }
/// <summary>
/// Gets or sets the default element name to use when using the Merge&lt;TBuilder>()
/// </summary>
public string RootElementName
{
get { return _rootElementName; }
set { ThrowHelper.ThrowIfNull(value, "RootElementName"); _rootElementName = value; }
}
private XmlFormatReader CloneWith(XmlReader rdr)
{
return new XmlFormatReader(rdr, Options);
}
private void NextElement()
{
while (!_input.IsStartElement() && _input.Read())
continue;
}
private static void Assert(bool cond)
{
if (!cond) throw new FormatException();
}
/// <summary>
/// Merge the provided builder as an element named <see cref="RootElementName"/> in the current context
/// </summary>
public override TBuilder Merge<TBuilder>(TBuilder builder, ExtensionRegistry registry)
{ return Merge(_rootElementName, builder, registry); }
/// <summary>
/// Merge the provided builder as an element of the current context
/// </summary>
public TBuilder Merge<TBuilder>(string element, TBuilder builder) where TBuilder : IBuilderLite
{ return Merge(element, builder, ExtensionRegistry.Empty); }
/// <summary>
/// Merge the provided builder as an element of the current context
/// </summary>
public TBuilder Merge<TBuilder>(string element, TBuilder builder, ExtensionRegistry registry) where TBuilder : IBuilderLite
{
string field;
Assert(PeekNext(out field) && field == element);
ReadMessage(builder, registry);
return builder;
}
/// <summary>
/// Peeks at the next field in the input stream and returns what information is available.
/// </summary>
/// <remarks>
/// This may be called multiple times without actually reading the field. Only after the field
/// is either read, or skipped, should PeekNext return a different value.
/// </remarks>
protected override bool PeekNext(out string field)
{
NextElement();
if(_input.IsStartElement())
{
field = _input.LocalName;
return true;
}
field = null;
return false;
}
/// <summary>
/// Causes the reader to skip past this field
/// </summary>
protected override void Skip()
{
if (_input.IsStartElement())
{
if (!_input.IsEmptyElement)
{
int depth = _input.Depth;
while (_input.Depth >= depth && _input.NodeType != XmlNodeType.EndElement)
Assert(_input.Read());
}
_input.Read();
}
}
/// <summary>
/// returns true if it was able to read a single value into the value reference. The value
/// stored may be of type System.String, System.Int32, or an IEnumLite from the IEnumLiteMap.
/// </summary>
protected override bool ReadEnum(ref object value)
{
int number;
string temp;
if (null != (temp = _input.GetAttribute("value")) && int.TryParse(temp, out number))
{
Skip();
value = number;
return true;
}
return base.ReadEnum(ref value);
}
/// <summary>
/// Returns true if it was able to read a String from the input
/// </summary>
protected override bool ReadAsText(ref string value, Type type)
{
Assert(_input.NodeType == XmlNodeType.Element);
value = _input.ReadElementContentAsString();
return true;
}
/// <summary>
/// Merges the input stream into the provided IBuilderLite
/// </summary>
protected override bool ReadMessage(IBuilderLite builder, ExtensionRegistry registry)
{
Assert(_input.IsStartElement());
if (!_input.IsEmptyElement)
{
int depth = _input.Depth;
XmlReader child = _input.ReadSubtree();
while (!child.IsStartElement() && child.Read())
continue;
child.Read();
builder.WeakMergeFrom(CloneWith(child), registry);
Assert(depth == _input.Depth && _input.NodeType == XmlNodeType.EndElement);
}
_input.Read();
return true;
}
private IEnumerable<string> NonNestedArrayItems(string field)
{
return base.ForeachArrayItem(field);
}
/// <summary>
/// Cursors through the array elements and stops at the end of the array
/// </summary>
protected override IEnumerable<string> ForeachArrayItem(string field)
{
bool isNested = (Options & XmlReaderOptions.ReadNestedArrays) != 0;
if (!isNested)
{
foreach (string item in NonNestedArrayItems(field))
yield return item;
yield break;
}
if (!_input.IsEmptyElement)
{
int depth = _input.Depth;
XmlReader child = _input.ReadSubtree();
while (!child.IsStartElement() && child.Read())
continue;
child.Read();
foreach (string item in CloneWith(child).NonNestedArrayItems("item"))
yield return item;
Assert(depth == _input.Depth && _input.NodeType == XmlNodeType.EndElement);
}
_input.Read();
yield break;
}
}
}
using System;
using System.IO;
using System.Xml;
using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers.Serialization
{
/// <summary>
/// Writes a proto buffer to an XML document or fragment. .NET 3.5 users may also
/// use this class to produce Json by setting the options to support Json and providing
/// an XmlWriter obtained from <see cref="System.Runtime.Serialization.Json.JsonReaderWriterFactory"/>.
/// </summary>
public class XmlFormatWriter : AbstractTextWriter
{
public const string DefaultRootElementName = "root";
private const int NestedArrayFlag = 0x0001;
private readonly XmlWriter _output;
private string _rootElementName;
static XmlWriterSettings DefaultSettings
{
get { return new XmlWriterSettings() {CheckCharacters = false, NewLineHandling = NewLineHandling.Entitize}; }
}
/// <summary>
/// Constructs the XmlFormatWriter to write to the given TextWriter
/// </summary>
public XmlFormatWriter(TextWriter output) : this(XmlWriter.Create(output, DefaultSettings)) { }
/// <summary>
/// Constructs the XmlFormatWriter to write to the given stream
/// </summary>
public XmlFormatWriter(Stream output) : this(XmlWriter.Create(output, DefaultSettings)) { }
/// <summary>
/// Constructs the XmlFormatWriter to write to the given XmlWriter
/// </summary>
public XmlFormatWriter(XmlWriter output)
{
_output = output;
_rootElementName = DefaultRootElementName;
}
/// <summary>
/// Closes the underlying XmlTextWriter
/// </summary>
protected override void Dispose(bool disposing)
{
if(disposing)
_output.Close();
}
/// <summary>
/// Gets or sets the default element name to use when using the Merge&lt;TBuilder>()
/// </summary>
public string RootElementName
{
get { return _rootElementName; }
set { ThrowHelper.ThrowIfNull(value, "RootElementName"); _rootElementName = value; }
}
/// <summary>
/// Gets or sets the options to use while generating the XML
/// </summary>
public XmlWriterOptions Options { get; set; }
private bool TestOption(XmlWriterOptions option) { return (Options & option) != 0; }
/// <summary>
/// Writes a message as an element using the name defined in <see cref="RootElementName"/>
/// </summary>
public override void WriteMessage(IMessageLite message)
{ WriteMessage(_rootElementName, message); }
/// <summary>
/// Writes a message as an element with the given name
/// </summary>
public override void WriteMessage(string elementName, IMessageLite message)
{
if (TestOption(XmlWriterOptions.OutputJsonTypes))
{
_output.WriteStartElement("root"); // json requires this is the root-element
_output.WriteAttributeString("type", "object");
}
else
_output.WriteStartElement(elementName);
message.WriteTo(this);
_output.WriteEndElement();
_output.Flush();
}
/// <summary>
/// Writes a message
/// </summary>
protected override void WriteMessageOrGroup(string field, IMessageLite message)
{
_output.WriteStartElement(field);
if (TestOption(XmlWriterOptions.OutputJsonTypes))
_output.WriteAttributeString("type", "object");
message.WriteTo(this);
_output.WriteEndElement();
}
/// <summary>
/// Writes a String value
/// </summary>
protected override void WriteAsText(string field, string textValue, object typedValue)
{
_output.WriteStartElement(field);
if (TestOption(XmlWriterOptions.OutputJsonTypes))
{
if (typedValue is int || typedValue is uint || typedValue is long || typedValue is ulong || typedValue is double || typedValue is float)
_output.WriteAttributeString("type", "number");
else if (typedValue is bool)
_output.WriteAttributeString("type", "boolean");
}
_output.WriteString(textValue);
//Empty strings should not be written as empty elements '<item/>', rather as '<item></item>'
if (_output.WriteState == WriteState.Element)
_output.WriteRaw("");
_output.WriteEndElement();
}
/// <summary>
/// Writes an array of field values
/// </summary>
protected override void WriteArray(FieldType fieldType, string field, System.Collections.IEnumerable items)
{
//see if it's empty
System.Collections.IEnumerator eitems = items.GetEnumerator();
try { if (!eitems.MoveNext()) return; }
finally
{ if (eitems is IDisposable) ((IDisposable) eitems).Dispose(); }
if (TestOption(XmlWriterOptions.OutputNestedArrays | XmlWriterOptions.OutputJsonTypes))
{
_output.WriteStartElement(field);
if (TestOption(XmlWriterOptions.OutputJsonTypes))
_output.WriteAttributeString("type", "array");
base.WriteArray(fieldType, "item", items);
_output.WriteEndElement();
}
else
base.WriteArray(fieldType, field, items);
}
/// <summary>
/// Writes a System.Enum by the numeric and textual value
/// </summary>
protected override void WriteEnum(string field, int number, string name)
{
_output.WriteStartElement(field);
if (!TestOption(XmlWriterOptions.OutputJsonTypes) && TestOption(XmlWriterOptions.OutputEnumValues))
_output.WriteAttributeString("value", XmlConvert.ToString(number));
_output.WriteString(name);
_output.WriteEndElement();
}
}
}
using System;
namespace Google.ProtocolBuffers.Serialization
{
/// <summary>
/// Options available for the xml reader output
/// </summary>
[Flags]
public enum XmlReaderOptions
{
/// <summary> Simple xml formatting with no attributes </summary>
None,
/// <summary> Requires that arrays items are nested in an &lt;item> element </summary>
ReadNestedArrays = 1,
}
}
\ No newline at end of file
using System;
namespace Google.ProtocolBuffers.Serialization
{
/// <summary>
/// Options available for the xml writer output
/// </summary>
[Flags]
public enum XmlWriterOptions
{
/// <summary> Simple xml formatting with no attributes </summary>
None,
/// <summary> Writes the 'value' attribute on all enumerations with the numeric identifier </summary>
OutputEnumValues = 0x1,
/// <summary> Embeds array items into child &lt;item> elements </summary>
OutputNestedArrays = 0x4,
/// <summary> Outputs the 'type' attribute for compatibility with the <see cref="System.Runtime.Serialization.Json.JsonReaderWriterFactory">JsonReaderWriterFactory</see> </summary>
/// <remarks> This option must, by nessessity, also enable NestedArrayItems </remarks>
OutputJsonTypes = 0x8,
}
}
\ No newline at end of file
......@@ -178,24 +178,24 @@ namespace Google.ProtocolBuffers
{
foreach (ulong value in varintList)
{
output.WriteUInt64(fieldNumber, UnknownFieldName, value);
output.WriteUnknownField(fieldNumber, WireFormat.WireType.Varint, value);
}
foreach (uint value in fixed32List)
{
output.WriteFixed32(fieldNumber, UnknownFieldName, value);
output.WriteUnknownField(fieldNumber, WireFormat.WireType.Fixed32, value);
}
foreach (ulong value in fixed64List)
{
output.WriteFixed64(fieldNumber, UnknownFieldName, value);
output.WriteUnknownField(fieldNumber, WireFormat.WireType.Fixed64, value);
}
foreach (ByteString value in lengthDelimitedList)
{
output.WriteBytes(fieldNumber, UnknownFieldName, value);
output.WriteUnknownBytes(fieldNumber, value);
}
foreach (UnknownFieldSet value in groupList)
{
#pragma warning disable 0612
output.WriteUnknownGroup(fieldNumber, UnknownFieldName, value);
output.WriteUnknownGroup(fieldNumber, value);
#pragma warning restore 0612
}
}
......
......@@ -446,6 +446,12 @@ namespace Google.ProtocolBuffers
[CLSCompliant(false)]
public bool MergeFieldFrom(uint tag, ICodedInputStream input)
{
if (tag == 0)
{
input.SkipField();
return true;
}
int number = WireFormat.GetTagFieldNumber(tag);
switch (WireFormat.GetTagWireType(tag))
{
......
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