Commit 2e6dc12f authored by Jon Skeet's avatar Jon Skeet

Write/Read delimited messages

parent 43da7ae3
......@@ -174,6 +174,12 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
public static PhoneNumber ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
}
public static PhoneNumber ParseDelimitedFrom(global::System.IO.Stream input) {
return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
}
public static PhoneNumber ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
}
public static PhoneNumber ParseFrom(pb::CodedInputStream input) {
return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
}
......@@ -217,6 +223,9 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
}
public override PhoneNumber BuildPartial() {
if (result == null) {
throw new global::System.InvalidOperationException("build() has already been called on this Builder");
}
PhoneNumber returnMe = result;
result = null;
return returnMe;
......@@ -446,6 +455,12 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
public static Person ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
}
public static Person ParseDelimitedFrom(global::System.IO.Stream input) {
return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
}
public static Person ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
}
public static Person ParseFrom(pb::CodedInputStream input) {
return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
}
......@@ -489,6 +504,9 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
}
public override Person BuildPartial() {
if (result == null) {
throw new global::System.InvalidOperationException("build() has already been called on this Builder");
}
result.phone_.MakeReadOnly();
Person returnMe = result;
result = null;
......@@ -753,6 +771,12 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
public static AddressBook ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
}
public static AddressBook ParseDelimitedFrom(global::System.IO.Stream input) {
return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
}
public static AddressBook ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
}
public static AddressBook ParseFrom(pb::CodedInputStream input) {
return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
}
......@@ -796,6 +820,9 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
}
public override AddressBook BuildPartial() {
if (result == null) {
throw new global::System.InvalidOperationException("build() has already been called on this Builder");
}
result.person_.MakeReadOnly();
AddressBook returnMe = result;
result = null;
......
......@@ -218,6 +218,12 @@ namespace Google.ProtocolBuffers.ProtoGen {
writer.WriteLine("public static {0} ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {{", ClassName);
writer.WriteLine(" return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();");
writer.WriteLine("}");
writer.WriteLine("public static {0} ParseDelimitedFrom(global::System.IO.Stream input) {{", ClassName);
writer.WriteLine(" return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();");
writer.WriteLine("}");
writer.WriteLine("public static {0} ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {{", ClassName);
writer.WriteLine(" return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();");
writer.WriteLine("}");
writer.WriteLine("public static {0} ParseFrom(pb::CodedInputStream input) {{", ClassName);
writer.WriteLine(" return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();");
writer.WriteLine("}");
......@@ -325,6 +331,9 @@ namespace Google.ProtocolBuffers.ProtoGen {
writer.WriteLine("public override {0} BuildPartial() {{", ClassName);
writer.Indent();
writer.WriteLine("if (result == null) {");
writer.WriteLine(" throw new global::System.InvalidOperationException(\"build() has already been called on this Builder\");");
writer.WriteLine("}");
foreach (FieldDescriptor field in Descriptor.Fields) {
SourceGenerators.CreateFieldGenerator(field).GenerateBuildingCode(writer);
}
......
......@@ -141,6 +141,12 @@ namespace Google.ProtocolBuffers.TestProtos {
public static TestEmbedOptimizedForSize ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
}
public static TestEmbedOptimizedForSize ParseDelimitedFrom(global::System.IO.Stream input) {
return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
}
public static TestEmbedOptimizedForSize ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
}
public static TestEmbedOptimizedForSize ParseFrom(pb::CodedInputStream input) {
return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
}
......@@ -184,6 +190,9 @@ namespace Google.ProtocolBuffers.TestProtos {
}
public override TestEmbedOptimizedForSize BuildPartial() {
if (result == null) {
throw new global::System.InvalidOperationException("build() has already been called on this Builder");
}
result.repeatedMessage_.MakeReadOnly();
TestEmbedOptimizedForSize returnMe = result;
result = null;
......
......@@ -123,6 +123,12 @@ namespace Google.ProtocolBuffers.TestProtos {
public static ImportMessage ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
}
public static ImportMessage ParseDelimitedFrom(global::System.IO.Stream input) {
return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
}
public static ImportMessage ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
}
public static ImportMessage ParseFrom(pb::CodedInputStream input) {
return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
}
......@@ -166,6 +172,9 @@ namespace Google.ProtocolBuffers.TestProtos {
}
public override ImportMessage BuildPartial() {
if (result == null) {
throw new global::System.InvalidOperationException("build() has already been called on this Builder");
}
ImportMessage returnMe = result;
result = null;
return returnMe;
......
......@@ -136,6 +136,12 @@ namespace Google.ProtocolBuffers.TestProtos {
public static TestMessageSet ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
}
public static TestMessageSet ParseDelimitedFrom(global::System.IO.Stream input) {
return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
}
public static TestMessageSet ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
}
public static TestMessageSet ParseFrom(pb::CodedInputStream input) {
return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
}
......@@ -179,6 +185,9 @@ namespace Google.ProtocolBuffers.TestProtos {
}
public override TestMessageSet BuildPartial() {
if (result == null) {
throw new global::System.InvalidOperationException("build() has already been called on this Builder");
}
TestMessageSet returnMe = result;
result = null;
return returnMe;
......@@ -314,6 +323,12 @@ namespace Google.ProtocolBuffers.TestProtos {
public static TestMessageSetContainer ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
}
public static TestMessageSetContainer ParseDelimitedFrom(global::System.IO.Stream input) {
return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
}
public static TestMessageSetContainer ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
}
public static TestMessageSetContainer ParseFrom(pb::CodedInputStream input) {
return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
}
......@@ -357,6 +372,9 @@ namespace Google.ProtocolBuffers.TestProtos {
}
public override TestMessageSetContainer BuildPartial() {
if (result == null) {
throw new global::System.InvalidOperationException("build() has already been called on this Builder");
}
TestMessageSetContainer returnMe = result;
result = null;
return returnMe;
......@@ -542,6 +560,12 @@ namespace Google.ProtocolBuffers.TestProtos {
public static TestMessageSetExtension1 ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
}
public static TestMessageSetExtension1 ParseDelimitedFrom(global::System.IO.Stream input) {
return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
}
public static TestMessageSetExtension1 ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
}
public static TestMessageSetExtension1 ParseFrom(pb::CodedInputStream input) {
return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
}
......@@ -585,6 +609,9 @@ namespace Google.ProtocolBuffers.TestProtos {
}
public override TestMessageSetExtension1 BuildPartial() {
if (result == null) {
throw new global::System.InvalidOperationException("build() has already been called on this Builder");
}
TestMessageSetExtension1 returnMe = result;
result = null;
return returnMe;
......@@ -747,6 +774,12 @@ namespace Google.ProtocolBuffers.TestProtos {
public static TestMessageSetExtension2 ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
}
public static TestMessageSetExtension2 ParseDelimitedFrom(global::System.IO.Stream input) {
return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
}
public static TestMessageSetExtension2 ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
}
public static TestMessageSetExtension2 ParseFrom(pb::CodedInputStream input) {
return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
}
......@@ -790,6 +823,9 @@ namespace Google.ProtocolBuffers.TestProtos {
}
public override TestMessageSetExtension2 BuildPartial() {
if (result == null) {
throw new global::System.InvalidOperationException("build() has already been called on this Builder");
}
TestMessageSetExtension2 returnMe = result;
result = null;
return returnMe;
......@@ -992,6 +1028,12 @@ namespace Google.ProtocolBuffers.TestProtos {
public static Item ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
}
public static Item ParseDelimitedFrom(global::System.IO.Stream input) {
return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
}
public static Item ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
}
public static Item ParseFrom(pb::CodedInputStream input) {
return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
}
......@@ -1035,6 +1077,9 @@ namespace Google.ProtocolBuffers.TestProtos {
}
public override Item BuildPartial() {
if (result == null) {
throw new global::System.InvalidOperationException("build() has already been called on this Builder");
}
Item returnMe = result;
result = null;
return returnMe;
......@@ -1203,6 +1248,12 @@ namespace Google.ProtocolBuffers.TestProtos {
public static RawMessageSet ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
}
public static RawMessageSet ParseDelimitedFrom(global::System.IO.Stream input) {
return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
}
public static RawMessageSet ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
}
public static RawMessageSet ParseFrom(pb::CodedInputStream input) {
return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
}
......@@ -1246,6 +1297,9 @@ namespace Google.ProtocolBuffers.TestProtos {
}
public override RawMessageSet BuildPartial() {
if (result == null) {
throw new global::System.InvalidOperationException("build() has already been called on this Builder");
}
result.item_.MakeReadOnly();
RawMessageSet returnMe = result;
result = null;
......
......@@ -119,6 +119,12 @@ namespace Google.ProtocolBuffers.TestProtos {
public static TestOptimizedForSize ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
}
public static TestOptimizedForSize ParseDelimitedFrom(global::System.IO.Stream input) {
return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
}
public static TestOptimizedForSize ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
}
public static TestOptimizedForSize ParseFrom(pb::CodedInputStream input) {
return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
}
......@@ -162,6 +168,9 @@ namespace Google.ProtocolBuffers.TestProtos {
}
public override TestOptimizedForSize BuildPartial() {
if (result == null) {
throw new global::System.InvalidOperationException("build() has already been called on this Builder");
}
TestOptimizedForSize returnMe = result;
result = null;
return returnMe;
......@@ -274,6 +283,12 @@ namespace Google.ProtocolBuffers.TestProtos {
public static TestRequiredOptimizedForSize ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
}
public static TestRequiredOptimizedForSize ParseDelimitedFrom(global::System.IO.Stream input) {
return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
}
public static TestRequiredOptimizedForSize ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
}
public static TestRequiredOptimizedForSize ParseFrom(pb::CodedInputStream input) {
return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
}
......@@ -317,6 +332,9 @@ namespace Google.ProtocolBuffers.TestProtos {
}
public override TestRequiredOptimizedForSize BuildPartial() {
if (result == null) {
throw new global::System.InvalidOperationException("build() has already been called on this Builder");
}
TestRequiredOptimizedForSize returnMe = result;
result = null;
return returnMe;
......@@ -393,6 +411,12 @@ namespace Google.ProtocolBuffers.TestProtos {
public static TestOptionalOptimizedForSize ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
}
public static TestOptionalOptimizedForSize ParseDelimitedFrom(global::System.IO.Stream input) {
return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
}
public static TestOptionalOptimizedForSize ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
}
public static TestOptionalOptimizedForSize ParseFrom(pb::CodedInputStream input) {
return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
}
......@@ -436,6 +460,9 @@ namespace Google.ProtocolBuffers.TestProtos {
}
public override TestOptionalOptimizedForSize BuildPartial() {
if (result == null) {
throw new global::System.InvalidOperationException("build() has already been called on this Builder");
}
TestOptionalOptimizedForSize returnMe = result;
result = null;
return returnMe;
......
......@@ -29,6 +29,7 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using System.IO;
using System.Reflection;
using Google.ProtocolBuffers.Descriptors;
using Google.ProtocolBuffers.TestProtos;
......@@ -98,6 +99,23 @@ namespace Google.ProtocolBuffers {
Assert.AreEqual(rawBytes, rawBytes2);
}
[Test]
public void SerializeDelimited() {
MemoryStream stream = new MemoryStream();
TestUtil.GetAllSet().WriteDelimitedTo(stream);
stream.WriteByte(12);
TestUtil.GetPackedSet().WriteDelimitedTo(stream);
stream.WriteByte(34);
stream.Position = 0;
TestUtil.AssertAllFieldsSet(TestAllTypes.ParseDelimitedFrom(stream));
Assert.AreEqual(12, stream.ReadByte());
TestUtil.AssertPackedFieldsSet(TestPackedTypes.ParseDelimitedFrom(stream));
Assert.AreEqual(34, stream.ReadByte());
Assert.AreEqual(-1, stream.ReadByte());
}
[Test]
public void ParseExtensions() {
// TestAllTypes and TestAllExtensions should have compatible wire formats,
......@@ -133,7 +151,7 @@ namespace Google.ProtocolBuffers {
Assert.AreEqual(TestUtil.GetAllSet().SerializedSize, TestUtil.GetAllExtensionsSet().SerializedSize);
}
private void AssertFieldsInOrder(ByteString data) {
private static void AssertFieldsInOrder(ByteString data) {
CodedInputStream input = data.CreateCodedInput();
uint previousTag = 0;
......
......@@ -225,6 +225,16 @@ namespace Google.ProtocolBuffers {
return ThisBuilder;
}
public TBuilder MergeDelimitedFrom(Stream input, ExtensionRegistry extensionRegistry) {
int size = CodedInputStream.ReadRawVarint32(input);
Stream limitedStream = new LimitedInputStream(input, size);
return MergeFrom(limitedStream, extensionRegistry);
}
public TBuilder MergeDelimitedFrom(Stream input) {
return MergeDelimitedFrom(input, ExtensionRegistry.Empty);
}
public virtual IBuilder SetField(FieldDescriptor field, object value) {
this[field] = value;
return ThisBuilder;
......@@ -234,5 +244,70 @@ namespace Google.ProtocolBuffers {
this[field, index] = value;
return ThisBuilder;
}
/// <summary>
/// Stream implementation which proxies another stream, only allowing a certain amount
/// of data to be read. Note that this is only used to read delimited streams, so it
/// doesn't attempt to implement everything.
/// </summary>
private class LimitedInputStream : Stream {
private readonly Stream proxied;
private int bytesLeft;
internal LimitedInputStream(Stream proxied, int size) {
this.proxied = proxied;
bytesLeft = size;
}
public override bool CanRead {
get { return true; }
}
public override bool CanSeek {
get { return false; }
}
public override bool CanWrite {
get { return false; }
}
public override void Flush() {
}
public override long Length {
get { throw new NotImplementedException(); }
}
public override long Position {
get {
throw new NotImplementedException();
}
set {
throw new NotImplementedException();
}
}
public override int Read(byte[] buffer, int offset, int count) {
if (bytesLeft > 0) {
int bytesRead = proxied.Read(buffer, offset, Math.Min(bytesLeft, count));
bytesLeft -= bytesRead;
return bytesRead;
}
return 0;
}
public override long Seek(long offset, SeekOrigin origin) {
throw new NotImplementedException();
}
public override void SetLength(long value) {
throw new NotImplementedException();
}
public override void Write(byte[] buffer, int offset, int count) {
throw new NotImplementedException();
}
}
}
}
......@@ -205,6 +205,13 @@ namespace Google.ProtocolBuffers {
codedOutput.Flush();
}
public void WriteDelimitedTo(Stream output) {
CodedOutputStream codedOutput = CodedOutputStream.CreateInstance(output);
codedOutput.WriteRawVarint32((uint) SerializedSize);
WriteTo(codedOutput);
codedOutput.Flush();
}
public override bool Equals(object other) {
if (other == this) {
return true;
......
......@@ -141,7 +141,7 @@ namespace Google.ProtocolBuffers {
/// zero is not a valid tag number.
/// </summary>
public uint ReadTag() {
if (bufferPos == bufferSize && !RefillBuffer(false)) {
if (IsAtEnd) {
lastTag = 0;
return 0;
}
......@@ -457,6 +457,41 @@ namespace Google.ProtocolBuffers {
return (uint)result;
}
/// <summary>
/// Reads a varint from the input one byte at a time, so that it does not
/// read any bytes after the end of the varint. If you simply wrapped the
/// stream in a CodedInputStream and used ReadRawVarint32(Stream)}
/// then you would probably end up reading past the end of the varint since
/// CodedInputStream buffers its input.
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
internal static int ReadRawVarint32(Stream input) {
int result = 0;
int offset = 0;
for (; offset < 32; offset += 7) {
int b = input.ReadByte();
if (b == -1) {
throw InvalidProtocolBufferException.TruncatedMessage();
}
result |= (b & 0x7f) << offset;
if ((b & 0x80) == 0) {
return result;
}
}
// Keep reading up to 64 bits.
for (; offset < 64; offset += 7) {
int b = input.ReadByte();
if (b == -1) {
throw InvalidProtocolBufferException.TruncatedMessage();
}
if ((b & 0x80) == 0) {
return result;
}
}
throw InvalidProtocolBufferException.MalformedVarint();
}
/// <summary>
/// Read a raw varint from the stream.
/// </summary>
......@@ -555,6 +590,9 @@ namespace Google.ProtocolBuffers {
/// as you can without harming your app's functionality. Note that
/// size limits only apply when reading from an InputStream, not
/// when constructed around a raw byte array (nor with ByteString.NewCodedInput).
/// If you want to read several messages from a single CodedInputStream, you
/// can call ResetSizeCounter() after each message to avoid hitting the
/// size limit.
/// </remarks>
public int SetSizeLimit(int limit) {
if (limit < 0) {
......@@ -566,6 +604,13 @@ namespace Google.ProtocolBuffers {
}
#region Internal reading and buffer management
/// <summary>
/// Resets the current size counter to zero (see SetSizeLimit).
/// </summary>
public void ResetSizeCounter() {
totalBytesRetired = 0;
}
/// <summary>
/// Sets currentLimit to (current position) + byteLimit. This is called
/// when descending into a length-delimited embedded message. The previous
......@@ -621,6 +666,17 @@ namespace Google.ProtocolBuffers {
return currentAbsolutePosition >= currentLimit;
}
}
/// <summary>
/// Returns true if the stream has reached the end of the input. This is the
/// case if either the end of the underlying input source has been reached or
/// the stream has reached a limit created using PushLimit.
/// </summary>
public bool IsAtEnd {
get {
return bufferPos == bufferSize && !RefillBuffer(false);
}
}
/// <summary>
/// Called when buffer is empty to read more bytes from the
......@@ -649,6 +705,9 @@ namespace Google.ProtocolBuffers {
bufferPos = 0;
bufferSize = (input == null) ? 0 : input.Read(buffer, 0, buffer.Length);
if (bufferSize < 0) {
throw new InvalidOperationException("Stream.Read returned a negative count");
}
if (bufferSize == 0) {
if (mustSucceed) {
throw InvalidProtocolBufferException.TruncatedMessage();
......@@ -847,7 +906,7 @@ namespace Google.ProtocolBuffers {
throw InvalidProtocolBufferException.TruncatedMessage();
}
if (size < bufferSize - bufferPos) {
if (size <= bufferSize - bufferPos) {
// We have all the bytes we need already.
bufferPos += size;
} else {
......@@ -863,8 +922,9 @@ namespace Google.ProtocolBuffers {
if (input == null) {
throw InvalidProtocolBufferException.TruncatedMessage();
}
input.Seek(size - pos, SeekOrigin.Current);
if (input.Position > input.Length) {
long previousPosition = input.Position;
input.Position += size - pos;
if (input.Position != previousPosition + size - pos) {
throw InvalidProtocolBufferException.TruncatedMessage();
}
totalBytesRetired += size - pos;
......
......@@ -143,6 +143,12 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
public static CSharpFileOptions ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
}
public static CSharpFileOptions ParseDelimitedFrom(global::System.IO.Stream input) {
return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
}
public static CSharpFileOptions ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
}
public static CSharpFileOptions ParseFrom(pb::CodedInputStream input) {
return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
}
......@@ -186,6 +192,9 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
}
public override CSharpFileOptions BuildPartial() {
if (result == null) {
throw new global::System.InvalidOperationException("build() has already been called on this Builder");
}
CSharpFileOptions returnMe = result;
result = null;
return returnMe;
......@@ -336,6 +345,12 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
public static CSharpFieldOptions ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
}
public static CSharpFieldOptions ParseDelimitedFrom(global::System.IO.Stream input) {
return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
}
public static CSharpFieldOptions ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
}
public static CSharpFieldOptions ParseFrom(pb::CodedInputStream input) {
return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
}
......@@ -379,6 +394,9 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
}
public override CSharpFieldOptions BuildPartial() {
if (result == null) {
throw new global::System.InvalidOperationException("build() has already been called on this Builder");
}
CSharpFieldOptions returnMe = result;
result = null;
return returnMe;
......
......@@ -247,6 +247,20 @@ namespace Google.ProtocolBuffers {
/// Merge some unknown fields into the set for this message.
/// </summary>
TBuilder MergeUnknownFields(UnknownFieldSet unknownFields);
/// <summary>
/// Like MergeFrom(Stream), but does not read until the end of the file.
/// Instead, the size of the message (encoded as a varint) is read first,
/// then the message data. Use Message.WriteDelimitedTo(Stream) to
/// write messages in this format.
/// </summary>
/// <param name="input"></param>
TBuilder MergeDelimitedFrom(Stream input);
/// <summary>
/// Like MergeDelimitedFrom(Stream) but supporting extensions.
/// </summary>
TBuilder MergeDelimitedFrom(Stream input, ExtensionRegistry extensionRegistry);
#region Convenience methods
/// <summary>
......@@ -283,8 +297,9 @@ namespace Google.ProtocolBuffers {
/// MergeFrom(CodedInputStream). Note that this method always reads
/// the entire input (unless it throws an exception). If you want it to
/// stop earlier, you will need to wrap the input in a wrapper
/// stream which limits reading. Despite usually reading the entire
/// stream, this method never closes the stream.
/// stream which limits reading. Or, use IMessage.WriteDelimitedTo(Stream)
/// to write your message and MmergeDelimitedFrom(Stream) to read it.
/// Despite usually reading the entire stream, this method never closes the stream.
/// </summary>
TBuilder MergeFrom(Stream input);
......
......@@ -113,9 +113,26 @@ namespace Google.ProtocolBuffers {
/// Serializes the message and writes it to the given output stream.
/// This does not flush or close the stream.
/// </summary>
/// <param name="output"></param>
/// <remarks>
/// Protocol Buffers are not self-delimiting. Therefore, if you write
/// any more data to the stream after the message, you must somehow ensure
/// that the parser on the receiving end does not interpret this as being
/// part of the protocol message. One way of doing this is by writing the size
/// of the message before the data, then making sure you limit the input to
/// that size when receiving the data. Alternatively, use WriteDelimitedTo(Stream).
/// </remarks>
void WriteTo(CodedOutputStream output);
/// <summary>
/// Like WriteTo(Stream) but writes the size of the message as a varint before
/// writing the data. This allows more data to be written to the stream after the
/// message without the need to delimit the message data yourself. Use
/// IBuilder.MergeDelimitedFrom(Stream) or the static method
/// YourMessageType.ParseDelimitedFrom(Stream) to parse messages written by this method.
/// </summary>
/// <param name="output"></param>
void WriteDelimitedTo(Stream output);
/// <summary>
/// Returns the number of bytes required to encode this message.
/// The result is only computed on the first call and memoized after that.
......
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.IO;
using System.Reflection;
......
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace Google.ProtocolBuffers {
......
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