Commit 60fd773d authored by csharptest's avatar csharptest Committed by rogerk

Completed work and testing for manually reading/writing start/end message

parent 819b7154
...@@ -17,12 +17,6 @@ namespace Google.ProtocolBuffers.Serialization ...@@ -17,12 +17,6 @@ namespace Google.ProtocolBuffers.Serialization
/// <summary> Constructs a new reader </summary> /// <summary> Constructs a new reader </summary>
protected AbstractReader() { MaxDepth = DefaultMaxDepth; } protected AbstractReader() { MaxDepth = DefaultMaxDepth; }
/// <summary> Constructs a new child reader </summary>
protected AbstractReader(AbstractReader copyFrom)
{
_depth = copyFrom._depth + 1;
MaxDepth = copyFrom.MaxDepth;
}
/// <summary> Gets or sets the maximum recursion depth allowed </summary> /// <summary> Gets or sets the maximum recursion depth allowed </summary>
public int MaxDepth { get; set; } public int MaxDepth { get; set; }
...@@ -116,12 +110,12 @@ namespace Google.ProtocolBuffers.Serialization ...@@ -116,12 +110,12 @@ namespace Google.ProtocolBuffers.Serialization
/// <summary> /// <summary>
/// Reads the root-message preamble specific to this formatter /// Reads the root-message preamble specific to this formatter
/// </summary> /// </summary>
public abstract AbstractReader ReadStartMessage(); public abstract void ReadMessageStart();
/// <summary> /// <summary>
/// Reads the root-message close specific to this formatter /// Reads the root-message close specific to this formatter
/// </summary> /// </summary>
public abstract void ReadEndMessage(); public abstract void ReadMessageEnd();
/// <summary> /// <summary>
/// Merges the input stream into the provided IBuilderLite /// Merges the input stream into the provided IBuilderLite
......
...@@ -11,10 +11,6 @@ namespace Google.ProtocolBuffers.Serialization ...@@ -11,10 +11,6 @@ namespace Google.ProtocolBuffers.Serialization
{ {
/// <summary> Constructs a new reader </summary> /// <summary> Constructs a new reader </summary>
protected AbstractTextReader() { } protected AbstractTextReader() { }
/// <summary> Constructs a new child reader </summary>
protected AbstractTextReader(AbstractTextReader copyFrom)
: base(copyFrom)
{ }
/// <summary> /// <summary>
/// Reads a typed field as a string /// Reads a typed field as a string
......
...@@ -45,23 +45,23 @@ namespace Google.ProtocolBuffers.Serialization ...@@ -45,23 +45,23 @@ namespace Google.ProtocolBuffers.Serialization
/// <summary> /// <summary>
/// Used to write any nessary root-message preamble. After this call you can call /// Used to write any nessary root-message preamble. After this call you can call
/// IMessageLite.MergeTo(...) and complete the message with a call to EndMessage(). /// IMessageLite.MergeTo(...) and complete the message with a call to WriteMessageEnd().
/// These three calls are identical to just calling WriteMessage(message); /// These three calls are identical to just calling WriteMessage(message);
/// </summary> /// </summary>
/// <example> /// <example>
/// AbstractWriter writer; /// AbstractWriter writer;
/// writer.StartMessage(); /// writer.WriteMessageStart();
/// message.WriteTo(writer); /// message.WriteTo(writer);
/// writer.EndMessage(); /// writer.WriteMessageEnd();
/// // ... or, but not both ... /// // ... or, but not both ...
/// writer.WriteMessage(message); /// writer.WriteMessage(message);
/// </example> /// </example>
public abstract void StartMessage(); public abstract void WriteMessageStart();
/// <summary> /// <summary>
/// Used to complete a root-message previously started with a call to StartMessage() /// Used to complete a root-message previously started with a call to WriteMessageStart()
/// </summary> /// </summary>
public abstract void EndMessage(); public abstract void WriteMessageEnd();
/// <summary> /// <summary>
/// Writes a Boolean value /// Writes a Boolean value
......
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using Google.ProtocolBuffers.Descriptors; using Google.ProtocolBuffers.Descriptors;
...@@ -25,17 +25,14 @@ namespace Google.ProtocolBuffers.Serialization ...@@ -25,17 +25,14 @@ namespace Google.ProtocolBuffers.Serialization
/// <summary> /// <summary>
/// No-op /// No-op
/// </summary> /// </summary>
public override AbstractReader ReadStartMessage() public override void ReadMessageStart()
{ { }
return this;
}
/// <summary> /// <summary>
/// No-op /// No-op
/// </summary> /// </summary>
public override void ReadEndMessage() public override void ReadMessageEnd()
{ { }
}
/// <summary> /// <summary>
/// Merges the contents of stream into the provided message builder /// Merges the contents of stream into the provided message builder
......
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using Google.ProtocolBuffers.Descriptors; using Google.ProtocolBuffers.Descriptors;
...@@ -57,13 +57,13 @@ namespace Google.ProtocolBuffers.Serialization ...@@ -57,13 +57,13 @@ namespace Google.ProtocolBuffers.Serialization
/// <summary> /// <summary>
/// No-op /// No-op
/// </summary> /// </summary>
public override void StartMessage() public override void WriteMessageStart()
{ } { }
/// <summary> /// <summary>
/// No-op /// No-op
/// </summary> /// </summary>
public override void EndMessage() public override void WriteMessageEnd()
{ } { }
/// <summary> /// <summary>
......
...@@ -3,7 +3,7 @@ using System.IO; ...@@ -3,7 +3,7 @@ using System.IO;
using System.Xml; using System.Xml;
using System.Text; using System.Text;
namespace Google.ProtocolBuffers.Serialization namespace Google.ProtocolBuffers.Serialization.Http
{ {
/// <summary> /// <summary>
/// Extensions and helpers to abstract the reading/writing of messages by a client-specified content type. /// Extensions and helpers to abstract the reading/writing of messages by a client-specified content type.
...@@ -29,14 +29,14 @@ namespace Google.ProtocolBuffers.Serialization ...@@ -29,14 +29,14 @@ namespace Google.ProtocolBuffers.Serialization
else if (inputType == FormatType.Json) else if (inputType == FormatType.Json)
{ {
JsonFormatReader reader = JsonFormatReader.CreateInstance(input); JsonFormatReader reader = JsonFormatReader.CreateInstance(input);
codedInput = reader.ReadStartMessage(); codedInput = reader;
} }
else if (inputType == FormatType.Xml) else if (inputType == FormatType.Xml)
{ {
XmlFormatReader reader = XmlFormatReader.CreateInstance(input); XmlFormatReader reader = XmlFormatReader.CreateInstance(input);
reader.RootElementName = options.XmlReaderRootElementName; reader.RootElementName = options.XmlReaderRootElementName;
reader.Options = options.XmlReaderOptions; reader.Options = options.XmlReaderOptions;
codedInput = reader.ReadStartMessage(); codedInput = reader;
} }
else else
throw new NotSupportedException(); throw new NotSupportedException();
...@@ -56,6 +56,7 @@ namespace Google.ProtocolBuffers.Serialization ...@@ -56,6 +56,7 @@ namespace Google.ProtocolBuffers.Serialization
public static TBuilder MergeFrom<TBuilder>(this TBuilder builder, MessageFormatOptions options, string contentType, Stream input) where TBuilder : IBuilderLite public static TBuilder MergeFrom<TBuilder>(this TBuilder builder, MessageFormatOptions options, string contentType, Stream input) where TBuilder : IBuilderLite
{ {
ICodedInputStream codedInput = CreateInputStream(options, contentType, input); ICodedInputStream codedInput = CreateInputStream(options, contentType, input);
codedInput.ReadMessageStart();
return (TBuilder)builder.WeakMergeFrom(codedInput, options.ExtensionRegistry); return (TBuilder)builder.WeakMergeFrom(codedInput, options.ExtensionRegistry);
} }
...@@ -82,13 +83,12 @@ namespace Google.ProtocolBuffers.Serialization ...@@ -82,13 +83,12 @@ namespace Google.ProtocolBuffers.Serialization
{ {
writer.Formatted(); writer.Formatted();
} }
writer.StartMessage();
codedOutput = writer; codedOutput = writer;
} }
else if (outputType == FormatType.Xml) else if (outputType == FormatType.Xml)
{ {
XmlFormatWriter writer; XmlFormatWriter writer;
if (options.FormattedOutput) if (!options.FormattedOutput)
{ {
writer = XmlFormatWriter.CreateInstance(output); writer = XmlFormatWriter.CreateInstance(output);
} }
...@@ -99,16 +99,15 @@ namespace Google.ProtocolBuffers.Serialization ...@@ -99,16 +99,15 @@ namespace Google.ProtocolBuffers.Serialization
CheckCharacters = false, CheckCharacters = false,
NewLineHandling = NewLineHandling.Entitize, NewLineHandling = NewLineHandling.Entitize,
OmitXmlDeclaration = true, OmitXmlDeclaration = true,
Encoding = Encoding.UTF8, Encoding = new UTF8Encoding(false),
Indent = true, Indent = true,
IndentChars = " ", IndentChars = " ",
NewLineChars = Environment.NewLine, NewLineChars = Environment.NewLine,
}; };
writer = XmlFormatWriter.CreateInstance(XmlWriter.Create(output, settings)); writer = XmlFormatWriter.CreateInstance(XmlWriter.Create(output, settings));
} }
writer.RootElementName = options.XmlWriterRootElementName; writer.RootElementName = options.XmlWriterRootElementName;
writer.Options = options.XmlWriterOptions; writer.Options = options.XmlWriterOptions;
writer.StartMessage();
codedOutput = writer; codedOutput = writer;
} }
else else
...@@ -126,19 +125,17 @@ namespace Google.ProtocolBuffers.Serialization ...@@ -126,19 +125,17 @@ namespace Google.ProtocolBuffers.Serialization
/// <param name="output">The stream to write the message to</param> /// <param name="output">The stream to write the message to</param>
public static void WriteTo(this IMessageLite message, MessageFormatOptions options, string contentType, Stream output) public static void WriteTo(this IMessageLite message, MessageFormatOptions options, string contentType, Stream output)
{ {
using (ICodedOutputStream codedOutput = CreateOutputStream(options, contentType, output)) ICodedOutputStream codedOutput = CreateOutputStream(options, contentType, output);
{
message.WriteTo(codedOutput);
// This is effectivly done by Dispose(); however, if you need to finalize a message // Output the appropriate message preamble
// without disposing the underlying stream, this is the only way to do it. codedOutput.WriteMessageStart();
if (codedOutput is AbstractWriter)
((AbstractWriter)codedOutput).EndMessage();
codedOutput.Flush(); // Write the message content to the output
} message.WriteTo(codedOutput);
}
// Write the closing message fragment
codedOutput.WriteMessageEnd();
}
enum FormatType { ProtoBuffer, Json, Xml }; enum FormatType { ProtoBuffer, Json, Xml };
......
using System; using System;
namespace Google.ProtocolBuffers.Serialization namespace Google.ProtocolBuffers.Serialization.Http
{ {
/// <summary> /// <summary>
/// Defines control information for the various formatting used with HTTP services /// Defines control information for the various formatting used with HTTP services
......
...@@ -3,7 +3,7 @@ using System.Text; ...@@ -3,7 +3,7 @@ using System.Text;
using Google.ProtocolBuffers; using Google.ProtocolBuffers;
using System.IO; using System.IO;
namespace Google.ProtocolBuffers.Serialization namespace Google.ProtocolBuffers.Serialization.Http
{ {
/// <summary> /// <summary>
/// Extensions for the IRpcServerStub /// Extensions for the IRpcServerStub
...@@ -25,6 +25,7 @@ namespace Google.ProtocolBuffers.Serialization ...@@ -25,6 +25,7 @@ namespace Google.ProtocolBuffers.Serialization
string contentType, Stream input, string responseType, Stream output) string contentType, Stream input, string responseType, Stream output)
{ {
ICodedInputStream codedInput = MessageFormatFactory.CreateInputStream(options, contentType, input); ICodedInputStream codedInput = MessageFormatFactory.CreateInputStream(options, contentType, input);
codedInput.ReadMessageStart();
IMessageLite response = stub.CallMethod(methodName, codedInput, options.ExtensionRegistry); IMessageLite response = stub.CallMethod(methodName, codedInput, options.ExtensionRegistry);
response.WriteTo(options, responseType, output); response.WriteTo(options, responseType, output);
} }
......
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Xml; using System.Xml;
...@@ -103,19 +103,18 @@ namespace Google.ProtocolBuffers.Serialization ...@@ -103,19 +103,18 @@ namespace Google.ProtocolBuffers.Serialization
/// <summary> /// <summary>
/// Reads the root-message preamble specific to this formatter /// Reads the root-message preamble specific to this formatter
/// </summary> /// </summary>
public override AbstractReader ReadStartMessage() public override void ReadMessageStart()
{ {
_input.Consume('{'); _input.Consume('{');
_stopChar.Push('}'); _stopChar.Push('}');
_state = ReaderState.BeginObject; _state = ReaderState.BeginObject;
return this;
} }
/// <summary> /// <summary>
/// Reads the root-message close specific to this formatter /// Reads the root-message close specific to this formatter
/// </summary> /// </summary>
public override void ReadEndMessage() public override void ReadMessageEnd()
{ {
_input.Consume((char)_stopChar.Pop()); _input.Consume((char)_stopChar.Pop());
_state = ReaderState.EndValue; _state = ReaderState.EndValue;
...@@ -126,9 +125,9 @@ namespace Google.ProtocolBuffers.Serialization ...@@ -126,9 +125,9 @@ namespace Google.ProtocolBuffers.Serialization
/// </summary> /// </summary>
public override TBuilder Merge<TBuilder>(TBuilder builder, ExtensionRegistry registry) public override TBuilder Merge<TBuilder>(TBuilder builder, ExtensionRegistry registry)
{ {
AbstractReader rdr = ReadStartMessage(); ReadMessageStart();
builder.WeakMergeFrom(rdr, registry); builder.WeakMergeFrom(this, registry);
rdr.ReadEndMessage(); ReadMessageEnd();
return builder; return builder;
} }
......
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
...@@ -101,7 +101,7 @@ namespace Google.ProtocolBuffers.Serialization ...@@ -101,7 +101,7 @@ namespace Google.ProtocolBuffers.Serialization
private class JsonStreamWriter : JsonFormatWriter private class JsonStreamWriter : JsonFormatWriter
{ {
#if SILVERLIGHT2 || COMPACT_FRAMEWORK_35 #if SILVERLIGHT2 || COMPACT_FRAMEWORK_35
static readonly Encoding Encoding = Encoding.UTF8; static readonly Encoding Encoding = new UTF8Encoding(false);
#else #else
private static readonly Encoding Encoding = Encoding.ASCII; private static readonly Encoding Encoding = Encoding.ASCII;
#endif #endif
...@@ -244,9 +244,10 @@ namespace Google.ProtocolBuffers.Serialization ...@@ -244,9 +244,10 @@ namespace Google.ProtocolBuffers.Serialization
/// </summary> /// </summary>
protected override void Dispose(bool disposing) protected override void Dispose(bool disposing)
{ {
if (disposing && _counter.Count == 1) if (disposing)
{ {
EndMessage(); while(_counter.Count > 1)
WriteMessageEnd();
} }
base.Dispose(disposing); base.Dispose(disposing);
...@@ -458,17 +459,17 @@ namespace Google.ProtocolBuffers.Serialization ...@@ -458,17 +459,17 @@ namespace Google.ProtocolBuffers.Serialization
/// </summary> /// </summary>
public override void WriteMessage(IMessageLite message) public override void WriteMessage(IMessageLite message)
{ {
StartMessage(); WriteMessageStart();
message.WriteTo(this); message.WriteTo(this);
EndMessage(); WriteMessageEnd();
} }
/// <summary> /// <summary>
/// Used to write the root-message preamble, in json this is the left-curly brace '{'. /// Used to write the root-message preamble, in json this is the left-curly brace '{'.
/// After this call you can call IMessageLite.MergeTo(...) and complete the message with /// After this call you can call IMessageLite.MergeTo(...) and complete the message with
/// a call to EndMessage(). /// a call to WriteMessageEnd().
/// </summary> /// </summary>
public override void StartMessage() public override void WriteMessageStart()
{ {
if (_isArray) if (_isArray)
{ {
...@@ -479,9 +480,9 @@ namespace Google.ProtocolBuffers.Serialization ...@@ -479,9 +480,9 @@ namespace Google.ProtocolBuffers.Serialization
} }
/// <summary> /// <summary>
/// Used to complete a root-message previously started with a call to StartMessage() /// Used to complete a root-message previously started with a call to WriteMessageStart()
/// </summary> /// </summary>
public override void EndMessage() public override void WriteMessageEnd()
{ {
_counter.RemoveAt(_counter.Count - 1); _counter.RemoveAt(_counter.Count - 1);
WriteLine("}"); WriteLine("}");
......
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Xml; using System.Xml;
...@@ -14,8 +14,23 @@ namespace Google.ProtocolBuffers.Serialization ...@@ -14,8 +14,23 @@ namespace Google.ProtocolBuffers.Serialization
{ {
public const string DefaultRootElementName = XmlFormatWriter.DefaultRootElementName; public const string DefaultRootElementName = XmlFormatWriter.DefaultRootElementName;
private readonly XmlReader _input; private readonly XmlReader _input;
private readonly Stack<ElementStack> _elements;
private string _rootElementName; private string _rootElementName;
private struct ElementStack
{
public readonly string LocalName;
public readonly int Depth;
public readonly bool IsEmpty;
public ElementStack(string localName, int depth, bool isEmpty) : this()
{
LocalName = localName;
IsEmpty = isEmpty;
Depth = depth;
}
}
private static XmlReaderSettings DefaultSettings private static XmlReaderSettings DefaultSettings
{ {
get get
...@@ -72,20 +87,10 @@ namespace Google.ProtocolBuffers.Serialization ...@@ -72,20 +87,10 @@ namespace Google.ProtocolBuffers.Serialization
{ {
_input = input; _input = input;
_rootElementName = DefaultRootElementName; _rootElementName = DefaultRootElementName;
_elements = new Stack<ElementStack>();
Options = XmlReaderOptions.None; Options = XmlReaderOptions.None;
} }
/// <summary>
/// Constructs the XmlFormatReader with the XmlReader and options
/// </summary>
protected XmlFormatReader(XmlFormatReader copyFrom, XmlReader input)
: base(copyFrom)
{
_input = input;
_rootElementName = copyFrom._rootElementName;
Options = copyFrom.Options;
}
/// <summary> /// <summary>
/// Gets or sets the options to use when reading the xml /// Gets or sets the options to use when reading the xml
/// </summary> /// </summary>
...@@ -113,20 +118,6 @@ namespace Google.ProtocolBuffers.Serialization ...@@ -113,20 +118,6 @@ namespace Google.ProtocolBuffers.Serialization
} }
} }
private XmlFormatReader CloneWith(XmlReader rdr)
{
XmlFormatReader copy = new XmlFormatReader(this, rdr);
return copy;
}
private void NextElement()
{
while (!_input.IsStartElement() && _input.Read())
{
continue;
}
}
private static void Assert(bool cond) private static void Assert(bool cond)
{ {
if (!cond) if (!cond)
...@@ -138,36 +129,49 @@ namespace Google.ProtocolBuffers.Serialization ...@@ -138,36 +129,49 @@ namespace Google.ProtocolBuffers.Serialization
/// <summary> /// <summary>
/// Reads the root-message preamble specific to this formatter /// Reads the root-message preamble specific to this formatter
/// </summary> /// </summary>
public override AbstractReader ReadStartMessage() public override void ReadMessageStart()
{ {
return ReadStartMessage(_rootElementName); ReadMessageStart(_rootElementName);
} }
public AbstractReader ReadStartMessage(string element) /// <summary>
/// Reads the root-message preamble specific to this formatter
/// </summary>
public void ReadMessageStart(string element)
{ {
string field; while (!_input.IsStartElement() && _input.Read())
Assert(PeekNext(out field) && field == element);
XmlReader child = _input.ReadSubtree();
while (!child.IsStartElement() && child.Read())
{ {
continue; continue;
} }
child.Read(); Assert(_input.IsStartElement() && _input.LocalName == element);
return CloneWith(child); _elements.Push(new ElementStack(element, _input.Depth, _input.IsEmptyElement));
_input.Read();
} }
/// <summary> /// <summary>
/// Reads the root-message close specific to this formatter, MUST be called /// Reads the root-message close specific to this formatter, MUST be called
/// on the reader obtained from ReadStartMessage(string element). /// on the reader obtained from ReadMessageStart(string element).
/// </summary> /// </summary>
public override void ReadEndMessage() public override void ReadMessageEnd()
{ {
Assert(0 == _input.Depth); Assert(_elements.Count > 0);
if(_input.NodeType == XmlNodeType.EndElement)
ElementStack stop = _elements.Peek();
while (_input.NodeType != XmlNodeType.EndElement && _input.NodeType != XmlNodeType.Element
&& _input.Depth > stop.Depth && _input.Read())
{ {
continue;
}
if (!stop.IsEmpty)
{
Assert(_input.NodeType == XmlNodeType.EndElement
&& _input.LocalName == stop.LocalName
&& _input.Depth == stop.Depth);
_input.Read(); _input.Read();
} }
_elements.Pop();
} }
/// <summary> /// <summary>
...@@ -192,9 +196,9 @@ namespace Google.ProtocolBuffers.Serialization ...@@ -192,9 +196,9 @@ namespace Google.ProtocolBuffers.Serialization
public TBuilder Merge<TBuilder>(string element, TBuilder builder, ExtensionRegistry registry) public TBuilder Merge<TBuilder>(string element, TBuilder builder, ExtensionRegistry registry)
where TBuilder : IBuilderLite where TBuilder : IBuilderLite
{ {
string field; ReadMessageStart(element);
Assert(PeekNext(out field) && field == element); builder.WeakMergeFrom(this, registry);
ReadMessage(builder, registry); ReadMessageEnd();
return builder; return builder;
} }
...@@ -207,7 +211,21 @@ namespace Google.ProtocolBuffers.Serialization ...@@ -207,7 +211,21 @@ namespace Google.ProtocolBuffers.Serialization
/// </remarks> /// </remarks>
protected override bool PeekNext(out string field) protected override bool PeekNext(out string field)
{ {
NextElement(); ElementStack stopNode;
if (_elements.Count == 0)
{
stopNode = new ElementStack(null, _input.Depth - 1, false);
}
else
{
stopNode = _elements.Peek();
}
while (!_input.IsStartElement() && _input.Depth > stopNode.Depth && _input.Read())
{
continue;
}
if (_input.IsStartElement()) if (_input.IsStartElement())
{ {
field = _input.LocalName; field = _input.LocalName;
...@@ -270,20 +288,9 @@ namespace Google.ProtocolBuffers.Serialization ...@@ -270,20 +288,9 @@ namespace Google.ProtocolBuffers.Serialization
protected override bool ReadMessage(IBuilderLite builder, ExtensionRegistry registry) protected override bool ReadMessage(IBuilderLite builder, ExtensionRegistry registry)
{ {
Assert(_input.IsStartElement()); Assert(_input.IsStartElement());
ReadMessageStart(_input.LocalName);
if (!_input.IsEmptyElement) builder.WeakMergeFrom(this, registry);
{ ReadMessageEnd();
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; return true;
} }
...@@ -305,27 +312,16 @@ namespace Google.ProtocolBuffers.Serialization ...@@ -305,27 +312,16 @@ namespace Google.ProtocolBuffers.Serialization
{ {
yield return item; yield return item;
} }
yield break;
} }
if (!_input.IsEmptyElement) else
{ {
int depth = _input.Depth; ReadMessageStart(field);
XmlReader child = _input.ReadSubtree(); foreach (string item in NonNestedArrayItems("item"))
while (!child.IsStartElement() && child.Read())
{
continue;
}
child.Read();
foreach (string item in CloneWith(child).NonNestedArrayItems("item"))
{ {
yield return item; yield return item;
} }
Assert(depth == _input.Depth && _input.NodeType == XmlNodeType.EndElement); ReadMessageEnd();
} }
_input.Read();
yield break;
} }
} }
} }
\ No newline at end of file
using System; using System;
using System.Collections; using System.Collections;
using System.IO; using System.IO;
using System.Text; using System.Text;
...@@ -14,10 +14,12 @@ namespace Google.ProtocolBuffers.Serialization ...@@ -14,10 +14,12 @@ namespace Google.ProtocolBuffers.Serialization
/// </summary> /// </summary>
public class XmlFormatWriter : AbstractTextWriter public class XmlFormatWriter : AbstractTextWriter
{ {
private static readonly Encoding DefaultEncoding = new UTF8Encoding(false);
public const string DefaultRootElementName = "root"; public const string DefaultRootElementName = "root";
private const int NestedArrayFlag = 0x0001; private const int NestedArrayFlag = 0x0001;
private readonly XmlWriter _output; private readonly XmlWriter _output;
private string _rootElementName; private string _rootElementName;
private int _messageOpenCount;
private static XmlWriterSettings DefaultSettings(Encoding encoding) private static XmlWriterSettings DefaultSettings(Encoding encoding)
{ {
...@@ -43,7 +45,7 @@ namespace Google.ProtocolBuffers.Serialization ...@@ -43,7 +45,7 @@ namespace Google.ProtocolBuffers.Serialization
/// </summary> /// </summary>
public static XmlFormatWriter CreateInstance(Stream output) public static XmlFormatWriter CreateInstance(Stream output)
{ {
return new XmlFormatWriter(XmlWriter.Create(output, DefaultSettings(Encoding.UTF8))); return new XmlFormatWriter(XmlWriter.Create(output, DefaultSettings(DefaultEncoding)));
} }
/// <summary> /// <summary>
...@@ -65,6 +67,7 @@ namespace Google.ProtocolBuffers.Serialization ...@@ -65,6 +67,7 @@ namespace Google.ProtocolBuffers.Serialization
protected XmlFormatWriter(XmlWriter output) protected XmlFormatWriter(XmlWriter output)
{ {
_output = output; _output = output;
_messageOpenCount = 0;
_rootElementName = DefaultRootElementName; _rootElementName = DefaultRootElementName;
} }
...@@ -75,8 +78,8 @@ namespace Google.ProtocolBuffers.Serialization ...@@ -75,8 +78,8 @@ namespace Google.ProtocolBuffers.Serialization
{ {
if (disposing) if (disposing)
{ {
if (_output.WriteState != WriteState.Closed && _output.WriteState != WriteState.Start) while(_messageOpenCount > 0)
_output.WriteEndDocument(); WriteMessageEnd();
_output.Close(); _output.Close();
} }
...@@ -128,9 +131,9 @@ namespace Google.ProtocolBuffers.Serialization ...@@ -128,9 +131,9 @@ namespace Google.ProtocolBuffers.Serialization
/// <summary> /// <summary>
/// Used to write the root-message preamble, in xml this is open element for RootElementName, /// Used to write the root-message preamble, in xml this is open element for RootElementName,
/// by default "&lt;root&gt;". After this call you can call IMessageLite.MergeTo(...) and /// by default "&lt;root&gt;". After this call you can call IMessageLite.MergeTo(...) and
/// complete the message with a call to EndMessage(). /// complete the message with a call to WriteMessageEnd().
/// </summary> /// </summary>
public override void StartMessage() public override void WriteMessageStart()
{ {
StartMessage(_rootElementName); StartMessage(_rootElementName);
} }
...@@ -138,7 +141,7 @@ namespace Google.ProtocolBuffers.Serialization ...@@ -138,7 +141,7 @@ namespace Google.ProtocolBuffers.Serialization
/// <summary> /// <summary>
/// Used to write the root-message preamble, in xml this is open element for elementName. /// Used to write the root-message preamble, in xml this is open element for elementName.
/// After this call you can call IMessageLite.MergeTo(...) and complete the message with /// After this call you can call IMessageLite.MergeTo(...) and complete the message with
/// a call to EndMessage(). /// a call to WriteMessageEnd().
/// </summary> /// </summary>
public void StartMessage(string elementName) public void StartMessage(string elementName)
{ {
...@@ -151,15 +154,20 @@ namespace Google.ProtocolBuffers.Serialization ...@@ -151,15 +154,20 @@ namespace Google.ProtocolBuffers.Serialization
{ {
_output.WriteStartElement(elementName); _output.WriteStartElement(elementName);
} }
_messageOpenCount++;
} }
/// <summary> /// <summary>
/// Used to complete a root-message previously started with a call to StartMessage() /// Used to complete a root-message previously started with a call to WriteMessageStart()
/// </summary> /// </summary>
public override void EndMessage() public override void WriteMessageEnd()
{ {
if (_messageOpenCount <= 0)
throw new InvalidOperationException();
_output.WriteEndElement(); _output.WriteEndElement();
_output.Flush(); _output.Flush();
_messageOpenCount--;
} }
/// <summary> /// <summary>
...@@ -177,7 +185,7 @@ namespace Google.ProtocolBuffers.Serialization ...@@ -177,7 +185,7 @@ namespace Google.ProtocolBuffers.Serialization
{ {
StartMessage(elementName); StartMessage(elementName);
message.WriteTo(this); message.WriteTo(this);
EndMessage(); WriteMessageEnd();
} }
/// <summary> /// <summary>
......
...@@ -106,6 +106,7 @@ ...@@ -106,6 +106,7 @@
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ReflectionTester.cs" /> <Compile Include="ReflectionTester.cs" />
<Compile Include="ServiceTest.cs" /> <Compile Include="ServiceTest.cs" />
<Compile Include="TestMimeMessageFormats.cs" />
<Compile Include="TestProtos\UnitTestCSharpOptionsProtoFile.cs" /> <Compile Include="TestProtos\UnitTestCSharpOptionsProtoFile.cs" />
<Compile Include="TestProtos\UnitTestCustomOptionsProtoFile.cs" /> <Compile Include="TestProtos\UnitTestCustomOptionsProtoFile.cs" />
<Compile Include="TestProtos\UnitTestEmbedOptimizeForProtoFile.cs" /> <Compile Include="TestProtos\UnitTestEmbedOptimizeForProtoFile.cs" />
......
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Google.ProtocolBuffers.Serialization;
using Google.ProtocolBuffers.Serialization.Http;
using Google.ProtocolBuffers.TestProtos;
using NUnit.Framework;
namespace Google.ProtocolBuffers
{
[TestFixture]
public class TestMimeMessageFormats
{
// There is a whole host of various json mime types in use around the net, this is the set we accept...
readonly IEnumerable<string> JsonTypes = new string[] { "application/json", "application/x-json", "application/x-javascript", "text/javascript", "text/x-javascript", "text/x-json", "text/json" };
readonly IEnumerable<string> XmlTypes = new string[] { "text/xml", "application/xml" };
readonly IEnumerable<string> ProtobufTypes = new string[] { "application/binary", "application/x-protobuf", "application/vnd.google.protobuf" };
[Test]
public void TestReadJsonMimeTypes()
{
foreach (string type in JsonTypes)
{
Assert.IsTrue(
MessageFormatFactory.CreateInputStream(new MessageFormatOptions(), type, Stream.Null)
is JsonFormatReader);
}
Assert.IsTrue(
MessageFormatFactory.CreateInputStream(new MessageFormatOptions() { DefaultContentType = "application/json" }, null, Stream.Null)
is JsonFormatReader);
}
[Test]
public void TestWriteJsonMimeTypes()
{
foreach (string type in JsonTypes)
{
Assert.IsTrue(
MessageFormatFactory.CreateOutputStream(new MessageFormatOptions(), type, Stream.Null)
is JsonFormatWriter);
}
Assert.IsTrue(
MessageFormatFactory.CreateOutputStream(new MessageFormatOptions() { DefaultContentType = "application/json" }, null, Stream.Null)
is JsonFormatWriter);
}
[Test]
public void TestReadXmlMimeTypes()
{
foreach (string type in XmlTypes)
{
Assert.IsTrue(
MessageFormatFactory.CreateInputStream(new MessageFormatOptions(), type, Stream.Null)
is XmlFormatReader);
}
Assert.IsTrue(
MessageFormatFactory.CreateInputStream(new MessageFormatOptions() { DefaultContentType = "application/xml" }, null, Stream.Null)
is XmlFormatReader);
}
[Test]
public void TestWriteXmlMimeTypes()
{
foreach (string type in XmlTypes)
{
Assert.IsTrue(
MessageFormatFactory.CreateOutputStream(new MessageFormatOptions(), type, Stream.Null)
is XmlFormatWriter);
}
Assert.IsTrue(
MessageFormatFactory.CreateOutputStream(new MessageFormatOptions() { DefaultContentType = "application/xml" }, null, Stream.Null)
is XmlFormatWriter);
}
[Test]
public void TestReadProtoMimeTypes()
{
foreach (string type in ProtobufTypes)
{
Assert.IsTrue(
MessageFormatFactory.CreateInputStream(new MessageFormatOptions(), type, Stream.Null)
is CodedInputStream);
}
Assert.IsTrue(
MessageFormatFactory.CreateInputStream(new MessageFormatOptions() { DefaultContentType = "application/vnd.google.protobuf" }, null, Stream.Null)
is CodedInputStream);
}
[Test]
public void TestWriteProtoMimeTypes()
{
foreach (string type in ProtobufTypes)
{
Assert.IsTrue(
MessageFormatFactory.CreateOutputStream(new MessageFormatOptions(), type, Stream.Null)
is CodedOutputStream);
}
Assert.IsTrue(
MessageFormatFactory.CreateOutputStream(new MessageFormatOptions() { DefaultContentType = "application/vnd.google.protobuf" }, null, Stream.Null)
is CodedOutputStream);
}
[Test]
public void TestMergeFromJsonType()
{
TestXmlMessage msg = new TestXmlMessage.Builder().MergeFrom(
new MessageFormatOptions(), "application/json", new MemoryStream(Encoding.ASCII.GetBytes(
TestXmlMessage.CreateBuilder().SetText("a").SetNumber(1).Build().ToJson()
)))
.Build();
Assert.AreEqual("a", msg.Text);
Assert.AreEqual(1, msg.Number);
}
[Test]
public void TestMergeFromXmlType()
{
TestXmlMessage msg = new TestXmlMessage.Builder().MergeFrom(
new MessageFormatOptions(), "application/xml", new MemoryStream(Encoding.ASCII.GetBytes(
TestXmlMessage.CreateBuilder().SetText("a").SetNumber(1).Build().ToXml()
)))
.Build();
Assert.AreEqual("a", msg.Text);
Assert.AreEqual(1, msg.Number);
}
[Test]
public void TestMergeFromProtoType()
{
TestXmlMessage msg = new TestXmlMessage.Builder().MergeFrom(
new MessageFormatOptions(), "application/vnd.google.protobuf", new MemoryStream(
TestXmlMessage.CreateBuilder().SetText("a").SetNumber(1).Build().ToByteArray()
))
.Build();
Assert.AreEqual("a", msg.Text);
Assert.AreEqual(1, msg.Number);
}
[Test]
public void TestWriteToJsonType()
{
MemoryStream ms = new MemoryStream();
TestXmlMessage.CreateBuilder().SetText("a").SetNumber(1).Build()
.WriteTo(new MessageFormatOptions(), "application/json", ms);
Assert.AreEqual(@"{""text"":""a"",""number"":1}", Encoding.UTF8.GetString(ms.ToArray()));
}
[Test]
public void TestWriteToXmlType()
{
MemoryStream ms = new MemoryStream();
TestXmlMessage.CreateBuilder().SetText("a").SetNumber(1).Build()
.WriteTo(new MessageFormatOptions(), "application/xml", ms);
Assert.AreEqual("<root><text>a</text><number>1</number></root>", Encoding.UTF8.GetString(ms.ToArray()));
}
[Test]
public void TestWriteToProtoType()
{
MemoryStream ms = new MemoryStream();
TestXmlMessage.CreateBuilder().SetText("a").SetNumber(1).Build()
.WriteTo(new MessageFormatOptions(), "application/vnd.google.protobuf", ms);
byte[] bytes = TestXmlMessage.CreateBuilder().SetText("a").SetNumber(1).Build().ToByteArray();
Assert.AreEqual(bytes, ms.ToArray());
}
[Test]
public void TestXmlReaderOptions()
{
MemoryStream ms = new MemoryStream();
XmlFormatWriter.CreateInstance(ms)
.SetOptions(XmlWriterOptions.OutputNestedArrays)
.WriteMessage("my-root-node", TestXmlMessage.CreateBuilder().SetText("a").AddNumbers(1).AddNumbers(2).Build());
ms.Position = 0;
MessageFormatOptions options = new MessageFormatOptions()
{
XmlReaderOptions = XmlReaderOptions.ReadNestedArrays,
XmlReaderRootElementName = "my-root-node"
};
TestXmlMessage msg = new TestXmlMessage.Builder().MergeFrom(
options, "application/xml", ms)
.Build();
Assert.AreEqual("a", msg.Text);
Assert.AreEqual(1, msg.NumbersList[0]);
Assert.AreEqual(2, msg.NumbersList[1]);
}
[Test]
public void TestXmlWriterOptions()
{
TestXmlMessage message = TestXmlMessage.CreateBuilder().SetText("a").AddNumbers(1).AddNumbers(2).Build();
MessageFormatOptions options = new MessageFormatOptions()
{
XmlWriterOptions = XmlWriterOptions.OutputNestedArrays,
XmlWriterRootElementName = "root-node"
};
MemoryStream ms = new MemoryStream();
message.WriteTo(options, "application/xml", ms);
ms.Position = 0;
TestXmlMessage.Builder builder = TestXmlMessage.CreateBuilder();
XmlFormatReader.CreateInstance(ms)
.SetOptions(XmlReaderOptions.ReadNestedArrays)
.Merge("root-node", builder);
Assert.AreEqual("a", builder.Text);
Assert.AreEqual(1, builder.NumbersList[0]);
Assert.AreEqual(2, builder.NumbersList[1]);
}
[Test]
public void TestJsonFormatted()
{
MemoryStream ms = new MemoryStream();
TestXmlMessage.CreateBuilder().SetText("a").SetNumber(1).Build()
.WriteTo(new MessageFormatOptions() { FormattedOutput = true }, "application/json", ms);
Assert.AreEqual("{\r\n \"text\": \"a\",\r\n \"number\": 1\r\n}", Encoding.UTF8.GetString(ms.ToArray()));
}
[Test]
public void TestXmlFormatted()
{
MemoryStream ms = new MemoryStream();
TestXmlMessage.CreateBuilder().SetText("a").SetNumber(1).Build()
.WriteTo(new MessageFormatOptions() { FormattedOutput = true }, "application/xml", ms);
Assert.AreEqual("<root>\r\n <text>a</text>\r\n <number>1</number>\r\n</root>", Encoding.UTF8.GetString(ms.ToArray()));
}
}
}
\ No newline at end of file
...@@ -45,7 +45,7 @@ namespace Google.ProtocolBuffers ...@@ -45,7 +45,7 @@ namespace Google.ProtocolBuffers
using (TextWriter output = new StringWriter()) using (TextWriter output = new StringWriter())
using (AbstractWriter writer = JsonFormatWriter.CreateInstance(output)) using (AbstractWriter writer = JsonFormatWriter.CreateInstance(output))
{ {
writer.StartMessage(); //manually begin the message, output is '{' writer.WriteMessageStart(); //manually begin the message, output is '{'
writer.Flush(); writer.Flush();
Assert.AreEqual("{", output.ToString()); Assert.AreEqual("{", output.ToString());
...@@ -56,7 +56,7 @@ namespace Google.ProtocolBuffers ...@@ -56,7 +56,7 @@ namespace Google.ProtocolBuffers
writer.Flush(); writer.Flush();
Assert.AreEqual(@"{""valid"":true", output.ToString()); Assert.AreEqual(@"{""valid"":true", output.ToString());
writer.EndMessage(); //manually write the end message '}' writer.WriteMessageEnd(); //manually write the end message '}'
Assert.AreEqual(@"{""valid"":true}", output.ToString()); Assert.AreEqual(@"{""valid"":true}", output.ToString());
} }
} }
...@@ -65,13 +65,13 @@ namespace Google.ProtocolBuffers ...@@ -65,13 +65,13 @@ namespace Google.ProtocolBuffers
public void Example_ReadJsonUsingICodedInputStream() public void Example_ReadJsonUsingICodedInputStream()
{ {
TestXmlMessage.Builder builder = TestXmlMessage.CreateBuilder(); TestXmlMessage.Builder builder = TestXmlMessage.CreateBuilder();
AbstractReader reader = JsonFormatReader.CreateInstance(@"{""valid"":true}"); ICodedInputStream reader = JsonFormatReader.CreateInstance(@"{""valid"":true}");
AbstractReader stream = reader.ReadStartMessage(); //manually read the begin the message '{' reader.ReadMessageStart(); //manually read the begin the message '{'
builder.MergeFrom(stream); //write the message normally builder.MergeFrom(reader); //write the message normally
stream.ReadEndMessage(); //manually read the end message '}' reader.ReadMessageEnd(); //manually read the end message '}'
} }
protected string Content; protected string Content;
...@@ -401,6 +401,28 @@ namespace Google.ProtocolBuffers ...@@ -401,6 +401,28 @@ namespace Google.ProtocolBuffers
Assert.AreEqual(3, ordinal); Assert.AreEqual(3, ordinal);
Assert.AreEqual(3, builder.TextlinesCount); Assert.AreEqual(3, builder.TextlinesCount);
} }
[Test]
public void TestReadWriteJsonWithoutRoot()
{
TestXmlMessage.Builder builder = TestXmlMessage.CreateBuilder();
TestXmlMessage message = builder.SetText("abc").SetNumber(123).Build();
string Json;
using (StringWriter sw = new StringWriter())
{
ICodedOutputStream output = JsonFormatWriter.CreateInstance(sw);
message.WriteTo(output);
output.Flush();
Json = sw.ToString();
}
Assert.AreEqual(@"""text"":""abc"",""number"":123", Json);
ICodedInputStream input = JsonFormatReader.CreateInstance(Json);
TestXmlMessage copy = TestXmlMessage.CreateBuilder().MergeFrom(input).Build();
Assert.AreEqual(message, copy);
}
[Test,ExpectedException(typeof(RecursionLimitExceededException))] [Test,ExpectedException(typeof(RecursionLimitExceededException))]
public void TestRecursiveLimit() public void TestRecursiveLimit()
{ {
......
...@@ -48,12 +48,12 @@ namespace Google.ProtocolBuffers ...@@ -48,12 +48,12 @@ namespace Google.ProtocolBuffers
using (TextWriter output = new StringWriter()) using (TextWriter output = new StringWriter())
using (AbstractWriter writer = XmlFormatWriter.CreateInstance(output)) using (AbstractWriter writer = XmlFormatWriter.CreateInstance(output))
{ {
writer.StartMessage(); //manually begin the message, output is '{' writer.WriteMessageStart(); //manually begin the message, output is '{'
ICodedOutputStream stream = writer; ICodedOutputStream stream = writer;
message.WriteTo(stream); //write the message normally message.WriteTo(stream); //write the message normally
writer.EndMessage(); //manually write the end message '}' writer.WriteMessageEnd(); //manually write the end message '}'
Assert.AreEqual(@"<root><valid>true</valid></root>", output.ToString()); Assert.AreEqual(@"<root><valid>true</valid></root>", output.ToString());
} }
} }
...@@ -62,13 +62,13 @@ namespace Google.ProtocolBuffers ...@@ -62,13 +62,13 @@ namespace Google.ProtocolBuffers
public void Example_ReadXmlUsingICodedInputStream() public void Example_ReadXmlUsingICodedInputStream()
{ {
TestXmlMessage.Builder builder = TestXmlMessage.CreateBuilder(); TestXmlMessage.Builder builder = TestXmlMessage.CreateBuilder();
AbstractReader reader = XmlFormatReader.CreateInstance(@"<root><valid>true</valid></root>"); ICodedInputStream reader = XmlFormatReader.CreateInstance(@"<root><valid>true</valid></root>");
AbstractReader stream = reader.ReadStartMessage(); //manually read the begin the message '{' reader.ReadMessageStart(); //manually read the begin the message '{'
builder.MergeFrom(stream); //write the message normally builder.MergeFrom(reader); //read the message normally
stream.ReadEndMessage(); //manually read the end message '}' reader.ReadMessageEnd(); //manually read the end message '}'
} }
[Test] [Test]
...@@ -387,13 +387,54 @@ namespace Google.ProtocolBuffers ...@@ -387,13 +387,54 @@ namespace Google.ProtocolBuffers
public void TestXmlReadEmptyRoot() public void TestXmlReadEmptyRoot()
{ {
TestXmlMessage.Builder builder = TestXmlMessage.CreateBuilder(); TestXmlMessage.Builder builder = TestXmlMessage.CreateBuilder();
AbstractReader reader = XmlFormatReader.CreateInstance(@"<root/>"); ICodedInputStream reader = XmlFormatReader.CreateInstance(@"<root/>");
AbstractReader stream = reader.ReadStartMessage(); //manually read the begin the message '{' reader.ReadMessageStart(); //manually read the begin the message '{'
builder.MergeFrom(stream); //write the message normally builder.MergeFrom(reader); //write the message normally
stream.ReadEndMessage(); //manually read the end message '}' reader.ReadMessageEnd(); //manually read the end message '}'
}
[Test]
public void TestXmlReadEmptyChild()
{
TestXmlMessage.Builder builder = TestXmlMessage.CreateBuilder();
ICodedInputStream reader = XmlFormatReader.CreateInstance(@"<root><text /></root>");
reader.ReadMessageStart(); //manually read the begin the message '{'
builder.MergeFrom(reader); //write the message normally
Assert.IsTrue(builder.HasText);
Assert.AreEqual(String.Empty, builder.Text);
}
[Test]
public void TestXmlReadWriteWithoutRoot()
{
TestXmlMessage.Builder builder = TestXmlMessage.CreateBuilder();
TestXmlMessage message = builder.SetText("abc").SetNumber(123).Build();
string xml;
using (StringWriter sw = new StringWriter())
{
ICodedOutputStream output = XmlFormatWriter.CreateInstance(
XmlWriter.Create(sw, new XmlWriterSettings() { ConformanceLevel = ConformanceLevel.Fragment }));
message.WriteTo(output);
output.Flush();
xml = sw.ToString();
}
Assert.AreEqual("<text>abc</text><number>123</number>", xml);
TestXmlMessage copy;
using (XmlReader xr = XmlReader.Create(new StringReader(xml), new XmlReaderSettings() { ConformanceLevel = ConformanceLevel.Fragment }))
{
ICodedInputStream input = XmlFormatReader.CreateInstance(xr);
copy = TestXmlMessage.CreateBuilder().MergeFrom(input).Build();
}
Assert.AreEqual(message, copy);
} }
[Test, ExpectedException(typeof(RecursionLimitExceededException))] [Test, ExpectedException(typeof(RecursionLimitExceededException))]
......
...@@ -144,6 +144,9 @@ namespace Google.ProtocolBuffers ...@@ -144,6 +144,9 @@ namespace Google.ProtocolBuffers
#endregion #endregion
void ICodedInputStream.ReadMessageStart() { }
void ICodedInputStream.ReadMessageEnd() { }
#region Validation #region Validation
/// <summary> /// <summary>
......
...@@ -136,6 +136,9 @@ namespace Google.ProtocolBuffers ...@@ -136,6 +136,9 @@ namespace Google.ProtocolBuffers
} }
} }
void ICodedOutputStream.WriteMessageStart() { }
void ICodedOutputStream.WriteMessageEnd() { Flush(); }
#region Writing of unknown fields #region Writing of unknown fields
[Obsolete] [Obsolete]
......
...@@ -45,6 +45,24 @@ namespace Google.ProtocolBuffers ...@@ -45,6 +45,24 @@ namespace Google.ProtocolBuffers
{ {
public interface ICodedInputStream public interface ICodedInputStream
{ {
/// <summary>
/// Reads any message initialization data expected from the input stream
/// </summary>
/// <remarks>
/// This is primarily used by text formats and unnecessary for protobuffers' own
/// binary format. The API for MessageStart/End was added for consistent handling
/// of output streams regardless of the actual writer implementation.
/// </remarks>
void ReadMessageStart();
/// <summary>
/// Reads any message finalization data expected from the input stream
/// </summary>
/// <remarks>
/// This is primarily used by text formats and unnecessary for protobuffers' own
/// binary format. The API for MessageStart/End was added for consistent handling
/// of output streams regardless of the actual writer implementation.
/// </remarks>
void ReadMessageEnd();
/// <summary> /// <summary>
/// Attempt to read a field tag, returning false if we have reached the end /// Attempt to read a field tag, returning false if we have reached the end
/// of the input data. /// of the input data.
......
...@@ -51,6 +51,24 @@ namespace Google.ProtocolBuffers ...@@ -51,6 +51,24 @@ namespace Google.ProtocolBuffers
/// </summary> /// </summary>
public interface ICodedOutputStream : IDisposable public interface ICodedOutputStream : IDisposable
{ {
/// <summary>
/// Writes any message initialization data needed to the output stream
/// </summary>
/// <remarks>
/// This is primarily used by text formats and unnecessary for protobuffers' own
/// binary format. The API for MessageStart/End was added for consistent handling
/// of output streams regardless of the actual writer implementation.
/// </remarks>
void WriteMessageStart();
/// <summary>
/// Writes any message finalization data needed to the output stream
/// </summary>
/// <remarks>
/// This is primarily used by text formats and unnecessary for protobuffers' own
/// binary format. The API for MessageStart/End was added for consistent handling
/// of output streams regardless of the actual writer implementation.
/// </remarks>
void WriteMessageEnd();
/// <summary> /// <summary>
/// Indicates that all temporary buffers be written to the final output. /// Indicates that all temporary buffers be written to the final output.
/// </summary> /// </summary>
......
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