aboutsummaryrefslogtreecommitdiff
path: root/src/ProtocolBuffers
diff options
context:
space:
mode:
Diffstat (limited to 'src/ProtocolBuffers')
-rw-r--r--src/ProtocolBuffers/AbstractBuilder.cs234
-rw-r--r--src/ProtocolBuffers/AbstractBuilderLite.cs232
-rw-r--r--src/ProtocolBuffers/AbstractMessage.cs104
-rw-r--r--src/ProtocolBuffers/AbstractMessageLite.cs133
-rw-r--r--src/ProtocolBuffers/ByteString.cs7
-rw-r--r--src/ProtocolBuffers/CodedInputStream.cs11
-rw-r--r--src/ProtocolBuffers/CodedOutputStream.cs53
-rw-r--r--src/ProtocolBuffers/DescriptorProtos/CSharpOptions.cs2
-rw-r--r--src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs238
-rw-r--r--src/ProtocolBuffers/Descriptors/EnumDescriptor.cs14
-rw-r--r--src/ProtocolBuffers/Descriptors/EnumValueDescriptor.cs2
-rw-r--r--src/ProtocolBuffers/Descriptors/FieldDescriptor.cs21
-rw-r--r--src/ProtocolBuffers/Descriptors/FieldMappingAttribute.cs26
-rw-r--r--src/ProtocolBuffers/DynamicMessage.cs11
-rw-r--r--src/ProtocolBuffers/EnumLite.cs106
-rw-r--r--src/ProtocolBuffers/ExtendableBuilder.cs8
-rw-r--r--src/ProtocolBuffers/ExtendableBuilderLite.cs262
-rw-r--r--src/ProtocolBuffers/ExtendableMessage.cs8
-rw-r--r--src/ProtocolBuffers/ExtendableMessageLite.cs184
-rw-r--r--src/ProtocolBuffers/ExtensionInfo.cs26
-rw-r--r--src/ProtocolBuffers/ExtensionRegistry.cs62
-rw-r--r--src/ProtocolBuffers/ExtensionRegistryLite.cs179
-rw-r--r--src/ProtocolBuffers/FieldAccess/RepeatedMessageAccessor.cs2
-rw-r--r--src/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs2
-rw-r--r--src/ProtocolBuffers/FieldSet.cs199
-rw-r--r--src/ProtocolBuffers/GeneratedBuilder.cs8
-rw-r--r--src/ProtocolBuffers/GeneratedBuilderLite.cs117
-rw-r--r--src/ProtocolBuffers/GeneratedExtensionBase.cs14
-rw-r--r--src/ProtocolBuffers/GeneratedExtensionLite.cs294
-rw-r--r--src/ProtocolBuffers/GeneratedMessage.cs4
-rw-r--r--src/ProtocolBuffers/GeneratedMessageLite.cs132
-rw-r--r--src/ProtocolBuffers/IBuilder.cs75
-rw-r--r--src/ProtocolBuffers/IBuilderLite.cs210
-rw-r--r--src/ProtocolBuffers/IMessage.cs38
-rw-r--r--src/ProtocolBuffers/IMessageLite.cs179
-rw-r--r--src/ProtocolBuffers/Properties/AssemblyInfo.cs6
-rw-r--r--src/ProtocolBuffers/ProtocolBuffers.csproj23
-rw-r--r--src/ProtocolBuffers/ProtocolBuffersLite.csproj115
-rw-r--r--src/ProtocolBuffers/SortedList.cs12
-rw-r--r--src/ProtocolBuffers/TextFormat.cs14
-rw-r--r--src/ProtocolBuffers/UninitializedMessageException.cs36
-rw-r--r--src/ProtocolBuffers/UnknownField.cs4
-rw-r--r--src/ProtocolBuffers/UnknownFieldSet.cs109
-rw-r--r--src/ProtocolBuffers/WireFormat.cs4
44 files changed, 2990 insertions, 530 deletions
diff --git a/src/ProtocolBuffers/AbstractBuilder.cs b/src/ProtocolBuffers/AbstractBuilder.cs
index a60ff0aa..0d1279c7 100644
--- a/src/ProtocolBuffers/AbstractBuilder.cs
+++ b/src/ProtocolBuffers/AbstractBuilder.cs
@@ -42,93 +42,57 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// Implementation of the non-generic IMessage interface as far as possible.
/// </summary>
- public abstract class AbstractBuilder<TMessage, TBuilder> : IBuilder<TMessage, TBuilder>
+ public abstract class AbstractBuilder<TMessage, TBuilder> : AbstractBuilderLite<TMessage, TBuilder>, IBuilder<TMessage, TBuilder>
where TMessage : AbstractMessage<TMessage, TBuilder>
where TBuilder : AbstractBuilder<TMessage, TBuilder> {
- protected abstract TBuilder ThisBuilder { get; }
-
#region Unimplemented members of IBuilder
public abstract UnknownFieldSet UnknownFields { get; set; }
- public abstract TBuilder MergeFrom(TMessage other);
- public abstract bool IsInitialized { get; }
public abstract IDictionary<FieldDescriptor, object> AllFields { get; }
public abstract object this[FieldDescriptor field] { get; set; }
public abstract MessageDescriptor DescriptorForType { get; }
public abstract int GetRepeatedFieldCount(FieldDescriptor field);
public abstract object this[FieldDescriptor field, int index] { get; set; }
public abstract bool HasField(FieldDescriptor field);
- public abstract TMessage Build();
- public abstract TMessage BuildPartial();
- public abstract TBuilder Clone();
- public abstract TMessage DefaultInstanceForType { get; }
public abstract IBuilder CreateBuilderForField(FieldDescriptor field);
public abstract TBuilder ClearField(FieldDescriptor field);
public abstract TBuilder AddRepeatedField(FieldDescriptor field, object value);
#endregion
- #region Implementation of methods which don't require type parameter information
- public IMessage WeakBuild() {
- return Build();
- }
-
- public IBuilder WeakAddRepeatedField(FieldDescriptor field, object value) {
- return AddRepeatedField(field, value);
- }
-
- public IBuilder WeakClear() {
- return Clear();
- }
-
- public IBuilder WeakMergeFrom(IMessage message) {
- return MergeFrom(message);
- }
-
- public IBuilder WeakMergeFrom(CodedInputStream input) {
- return MergeFrom(input);
- }
-
- public IBuilder WeakMergeFrom(CodedInputStream input, ExtensionRegistry registry) {
- return MergeFrom(input, registry);
- }
-
- public IBuilder WeakMergeFrom(ByteString data) {
- return MergeFrom(data);
- }
-
- public IBuilder WeakMergeFrom(ByteString data, ExtensionRegistry registry) {
- return MergeFrom(data, registry);
- }
-
- public IMessage WeakBuildPartial() {
- return BuildPartial();
- }
-
- public IBuilder WeakClone() {
- return Clone();
- }
-
- public IMessage WeakDefaultInstanceForType {
- get { return DefaultInstanceForType; }
- }
-
- public IBuilder WeakClearField(FieldDescriptor field) {
- return ClearField(field);
- }
- #endregion
-
public TBuilder SetUnknownFields(UnknownFieldSet fields) {
UnknownFields = fields;
return ThisBuilder;
}
- public virtual TBuilder Clear() {
+ public override TBuilder Clear() {
foreach(FieldDescriptor field in AllFields.Keys) {
ClearField(field);
}
return ThisBuilder;
}
+ public sealed override TBuilder MergeFrom(IMessageLite other) {
+ if (other is IMessage) {
+ return MergeFrom((IMessage) other);
+ }
+ throw new ArgumentException("MergeFrom(Message) can only merge messages of the same type.");
+ }
+
+ /// <summary>
+ /// Merge the specified other message into the message being
+ /// built. Merging occurs as follows. For each field:
+ /// For singular primitive fields, if the field is set in <paramref name="other"/>,
+ /// then <paramref name="other"/>'s value overwrites the value in this message.
+ /// For singular message fields, if the field is set in <paramref name="other"/>,
+ /// it is merged into the corresponding sub-message of this message using the same
+ /// merging rules.
+ /// For repeated fields, the elements in <paramref name="other"/> are concatenated
+ /// with the elements in this message.
+ /// </summary>
+ /// <param name="other"></param>
+ /// <returns></returns>
+ public abstract TBuilder MergeFrom(TMessage other);
+
public virtual TBuilder MergeFrom(IMessage other) {
if (other.DescriptorForType != DescriptorForType) {
throw new ArgumentException("MergeFrom(IMessage) can only merge messages of the same type.");
@@ -151,13 +115,13 @@ namespace Google.ProtocolBuffers {
}
} else if (field.MappedType == MappedType.Message) {
// Merge singular messages
- IMessage existingValue = (IMessage) this[field];
+ IMessageLite existingValue = (IMessageLite)this[field];
if (existingValue == existingValue.WeakDefaultInstanceForType) {
this[field] = entry.Value;
} else {
this[field] = existingValue.WeakCreateBuilderForType()
.WeakMergeFrom(existingValue)
- .WeakMergeFrom((IMessage) entry.Value)
+ .WeakMergeFrom((IMessageLite)entry.Value)
.WeakBuild();
}
} else {
@@ -165,14 +129,14 @@ namespace Google.ProtocolBuffers {
this[field] = entry.Value;
}
}
- return ThisBuilder;
- }
- public virtual TBuilder MergeFrom(CodedInputStream input) {
- return MergeFrom(input, ExtensionRegistry.Empty);
+ //Fix for unknown fields not merging, see java's AbstractMessage.Builder<T> line 236
+ MergeUnknownFields(other.UnknownFields);
+
+ return ThisBuilder;
}
- public virtual TBuilder MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry) {
+ public override TBuilder MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry) {
UnknownFieldSet.Builder unknownFields = UnknownFieldSet.CreateBuilder(UnknownFields);
unknownFields.MergeFrom(input, extensionRegistry, this);
UnknownFields = unknownFields.Build();
@@ -186,131 +150,65 @@ namespace Google.ProtocolBuffers {
return ThisBuilder;
}
- public virtual TBuilder MergeFrom(ByteString data) {
- CodedInputStream input = data.CreateCodedInput();
- MergeFrom(input);
- input.CheckLastTagWas(0);
+ public virtual IBuilder SetField(FieldDescriptor field, object value) {
+ this[field] = value;
return ThisBuilder;
}
- public virtual TBuilder MergeFrom(ByteString data, ExtensionRegistry extensionRegistry) {
- CodedInputStream input = data.CreateCodedInput();
- MergeFrom(input, extensionRegistry);
- input.CheckLastTagWas(0);
+ public virtual IBuilder SetRepeatedField(FieldDescriptor field, int index, object value) {
+ this[field, index] = value;
return ThisBuilder;
- }
+ }
- public virtual TBuilder MergeFrom(byte[] data) {
- CodedInputStream input = CodedInputStream.CreateInstance(data);
- MergeFrom(input);
- input.CheckLastTagWas(0);
- return ThisBuilder;
- }
+ #region Explicit Implementations
- public virtual TBuilder MergeFrom(byte[] data, ExtensionRegistry extensionRegistry) {
- CodedInputStream input = CodedInputStream.CreateInstance(data);
- MergeFrom(input, extensionRegistry);
- input.CheckLastTagWas(0);
- return ThisBuilder;
+ IMessage IBuilder.WeakBuild() {
+ return Build();
}
- public virtual TBuilder MergeFrom(Stream input) {
- CodedInputStream codedInput = CodedInputStream.CreateInstance(input);
- MergeFrom(codedInput);
- codedInput.CheckLastTagWas(0);
- return ThisBuilder;
+ IBuilder IBuilder.WeakAddRepeatedField(FieldDescriptor field, object value) {
+ return AddRepeatedField(field, value);
}
- public virtual TBuilder MergeFrom(Stream input, ExtensionRegistry extensionRegistry) {
- CodedInputStream codedInput = CodedInputStream.CreateInstance(input);
- MergeFrom(codedInput, extensionRegistry);
- codedInput.CheckLastTagWas(0);
- return ThisBuilder;
+ IBuilder IBuilder.WeakClear() {
+ return Clear();
}
- public TBuilder MergeDelimitedFrom(Stream input, ExtensionRegistry extensionRegistry) {
- int size = (int) CodedInputStream.ReadRawVarint32(input);
- Stream limitedStream = new LimitedInputStream(input, size);
- return MergeFrom(limitedStream, extensionRegistry);
+ IBuilder IBuilder.WeakMergeFrom(IMessage message) {
+ return MergeFrom(message);
}
- public TBuilder MergeDelimitedFrom(Stream input) {
- return MergeDelimitedFrom(input, ExtensionRegistry.Empty);
+ IBuilder IBuilder.WeakMergeFrom(CodedInputStream input) {
+ return MergeFrom(input);
}
- public virtual IBuilder SetField(FieldDescriptor field, object value) {
- this[field] = value;
- return ThisBuilder;
+ IBuilder IBuilder.WeakMergeFrom(CodedInputStream input, ExtensionRegistry registry) {
+ return MergeFrom(input, registry);
}
- public virtual IBuilder SetRepeatedField(FieldDescriptor field, int index, object value) {
- this[field, index] = value;
- return ThisBuilder;
+ IBuilder IBuilder.WeakMergeFrom(ByteString data) {
+ return MergeFrom(data);
}
- /// <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();
- }
- }
+ IBuilder IBuilder.WeakMergeFrom(ByteString data, ExtensionRegistry registry) {
+ return MergeFrom(data, registry);
+ }
- 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;
- }
+ IMessage IBuilder.WeakBuildPartial() {
+ return BuildPartial();
+ }
- public override long Seek(long offset, SeekOrigin origin) {
- throw new NotImplementedException();
- }
+ IBuilder IBuilder.WeakClone() {
+ return Clone();
+ }
- public override void SetLength(long value) {
- throw new NotImplementedException();
- }
+ IMessage IBuilder.WeakDefaultInstanceForType {
+ get { return DefaultInstanceForType; }
+ }
- public override void Write(byte[] buffer, int offset, int count) {
- throw new NotImplementedException();
- }
+ IBuilder IBuilder.WeakClearField(FieldDescriptor field) {
+ return ClearField(field);
}
+ #endregion
}
}
diff --git a/src/ProtocolBuffers/AbstractBuilderLite.cs b/src/ProtocolBuffers/AbstractBuilderLite.cs
new file mode 100644
index 00000000..c5fbf0ce
--- /dev/null
+++ b/src/ProtocolBuffers/AbstractBuilderLite.cs
@@ -0,0 +1,232 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// 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.
+#endregion
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Google.ProtocolBuffers {
+ /// <summary>
+ /// Implementation of the non-generic IMessage interface as far as possible.
+ /// </summary>
+ public abstract class AbstractBuilderLite<TMessage, TBuilder> : IBuilderLite<TMessage, TBuilder>
+ where TMessage : AbstractMessageLite<TMessage, TBuilder>
+ where TBuilder : AbstractBuilderLite<TMessage, TBuilder> {
+
+ protected abstract TBuilder ThisBuilder { get; }
+
+ public abstract bool IsInitialized { get; }
+
+ public abstract TBuilder Clear();
+
+ public abstract TBuilder Clone();
+
+ public abstract TMessage Build();
+
+ public abstract TMessage BuildPartial();
+
+ public abstract TBuilder MergeFrom(IMessageLite other);
+
+ public abstract TBuilder MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry);
+
+ public abstract TMessage DefaultInstanceForType { get; }
+
+ #region IBuilderLite<TMessage,TBuilder> Members
+
+ public virtual TBuilder MergeFrom(CodedInputStream input) {
+ return MergeFrom(input, ExtensionRegistry.CreateInstance());
+ }
+
+ public TBuilder MergeDelimitedFrom(Stream input) {
+ return MergeDelimitedFrom(input, ExtensionRegistry.CreateInstance());
+ }
+
+ public TBuilder MergeDelimitedFrom(Stream input, ExtensionRegistry extensionRegistry) {
+ int size = (int)CodedInputStream.ReadRawVarint32(input);
+ Stream limitedStream = new LimitedInputStream(input, size);
+ return MergeFrom(limitedStream, extensionRegistry);
+ }
+
+ public TBuilder MergeFrom(ByteString data) {
+ return MergeFrom(data, ExtensionRegistry.CreateInstance());
+ }
+
+ public TBuilder MergeFrom(ByteString data, ExtensionRegistry extensionRegistry) {
+ CodedInputStream input = data.CreateCodedInput();
+ MergeFrom(input, extensionRegistry);
+ input.CheckLastTagWas(0);
+ return ThisBuilder;
+ }
+
+ public TBuilder MergeFrom(byte[] data) {
+ CodedInputStream input = CodedInputStream.CreateInstance(data);
+ MergeFrom(input);
+ input.CheckLastTagWas(0);
+ return ThisBuilder;
+ }
+
+ public TBuilder MergeFrom(byte[] data, ExtensionRegistry extensionRegistry) {
+ CodedInputStream input = CodedInputStream.CreateInstance(data);
+ MergeFrom(input, extensionRegistry);
+ input.CheckLastTagWas(0);
+ return ThisBuilder;
+ }
+
+ public TBuilder MergeFrom(Stream input) {
+ CodedInputStream codedInput = CodedInputStream.CreateInstance(input);
+ MergeFrom(codedInput);
+ codedInput.CheckLastTagWas(0);
+ return ThisBuilder;
+ }
+
+ public TBuilder MergeFrom(Stream input, ExtensionRegistry extensionRegistry) {
+ CodedInputStream codedInput = CodedInputStream.CreateInstance(input);
+ MergeFrom(codedInput, extensionRegistry);
+ codedInput.CheckLastTagWas(0);
+ return ThisBuilder;
+ }
+
+ #endregion
+ #region Explicit definitions
+
+ IBuilderLite IBuilderLite.WeakClear() {
+ return Clear();
+ }
+
+ IBuilderLite IBuilderLite.WeakMergeFrom(IMessageLite message) {
+ return MergeFrom(message);
+ }
+
+ IBuilderLite IBuilderLite.WeakMergeFrom(ByteString data) {
+ return MergeFrom(data);
+ }
+
+ IBuilderLite IBuilderLite.WeakMergeFrom(ByteString data, ExtensionRegistry registry) {
+ return MergeFrom(data, registry);
+ }
+
+ IBuilderLite IBuilderLite.WeakMergeFrom(CodedInputStream input) {
+ return MergeFrom(input);
+ }
+
+ IBuilderLite IBuilderLite.WeakMergeFrom(CodedInputStream input, ExtensionRegistry registry) {
+ return MergeFrom(input, registry);
+ }
+
+ IMessageLite IBuilderLite.WeakBuild() {
+ return Build();
+ }
+
+ IMessageLite IBuilderLite.WeakBuildPartial() {
+ return BuildPartial();
+ }
+
+ IBuilderLite IBuilderLite.WeakClone() {
+ return Clone();
+ }
+
+ IMessageLite IBuilderLite.WeakDefaultInstanceForType {
+ get { return DefaultInstanceForType; }
+ }
+
+ #endregion
+ #region LimitedInputStream
+ /// <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 NotSupportedException(); }
+ }
+
+ public override long Position {
+ get {
+ throw new NotSupportedException();
+ }
+ set {
+ throw new NotSupportedException();
+ }
+ }
+
+ 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 NotSupportedException();
+ }
+
+ public override void SetLength(long value) {
+ throw new NotSupportedException();
+ }
+
+ public override void Write(byte[] buffer, int offset, int count) {
+ throw new NotSupportedException();
+ }
+ }
+ #endregion
+ }
+}
diff --git a/src/ProtocolBuffers/AbstractMessage.cs b/src/ProtocolBuffers/AbstractMessage.cs
index 086aac82..203b71a4 100644
--- a/src/ProtocolBuffers/AbstractMessage.cs
+++ b/src/ProtocolBuffers/AbstractMessage.cs
@@ -42,7 +42,7 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// Implementation of the non-generic IMessage interface as far as possible.
/// </summary>
- public abstract class AbstractMessage<TMessage, TBuilder> : IMessage<TMessage, TBuilder>
+ public abstract class AbstractMessage<TMessage, TBuilder> : AbstractMessageLite<TMessage, TBuilder>, IMessage<TMessage, TBuilder>
where TMessage : AbstractMessage<TMessage, TBuilder>
where TBuilder : AbstractBuilder<TMessage, TBuilder> {
/// <summary>
@@ -59,24 +59,13 @@ namespace Google.ProtocolBuffers {
public abstract int GetRepeatedFieldCount(FieldDescriptor field);
public abstract object this[FieldDescriptor field, int index] { get; }
public abstract UnknownFieldSet UnknownFields { get; }
- public abstract TMessage DefaultInstanceForType { get; }
- public abstract TBuilder CreateBuilderForType();
- public abstract TBuilder ToBuilder();
#endregion
-
- public IBuilder WeakCreateBuilderForType() {
- return CreateBuilderForType();
- }
-
- public IBuilder WeakToBuilder() {
- return ToBuilder();
- }
- public IMessage WeakDefaultInstanceForType {
- get { return DefaultInstanceForType; }
- }
-
- public virtual bool IsInitialized {
+ /// <summary>
+ /// Returns true iff all required fields in the message and all embedded
+ /// messages are set.
+ /// </summary>
+ public override bool IsInitialized {
get {
// Check that all required fields are present.
foreach (FieldDescriptor field in DescriptorForType.Fields) {
@@ -92,13 +81,13 @@ namespace Google.ProtocolBuffers {
if (field.IsRepeated) {
// We know it's an IList<T>, but not the exact type - so
// IEnumerable is the best we can do. (C# generics aren't covariant yet.)
- foreach (IMessage element in (IEnumerable) entry.Value) {
+ foreach (IMessageLite element in (IEnumerable)entry.Value) {
if (!element.IsInitialized) {
return false;
}
}
} else {
- if (!((IMessage)entry.Value).IsInitialized) {
+ if (!((IMessageLite)entry.Value).IsInitialized) {
return false;
}
}
@@ -112,7 +101,23 @@ namespace Google.ProtocolBuffers {
return TextFormat.PrintToString(this);
}
- public virtual void WriteTo(CodedOutputStream output) {
+ public sealed override void PrintTo(TextWriter writer) {
+ TextFormat.Print(this, writer);
+ }
+
+ /// <summary>
+ /// Serializes the message and writes it to the given output stream.
+ /// This does not flush or close the stream.
+ /// </summary>
+ /// <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>
+ public override void WriteTo(CodedOutputStream output) {
foreach (KeyValuePair<FieldDescriptor, object> entry in AllFields) {
FieldDescriptor field = entry.Key;
if (field.IsRepeated) {
@@ -147,7 +152,11 @@ namespace Google.ProtocolBuffers {
}
}
- public virtual int SerializedSize {
+ /// <summary>
+ /// Returns the number of bytes required to encode this message.
+ /// The result is only computed on the first call and memoized after that.
+ /// </summary>
+ public override int SerializedSize {
get {
if (memoizedSize != null) {
return memoizedSize.Value;
@@ -188,33 +197,12 @@ namespace Google.ProtocolBuffers {
}
}
- public ByteString ToByteString() {
- ByteString.CodedBuilder output = new ByteString.CodedBuilder(SerializedSize);
- WriteTo(output.CodedOutput);
- return output.Build();
- }
-
- public byte[] ToByteArray() {
- byte[] result = new byte[SerializedSize];
- CodedOutputStream output = CodedOutputStream.CreateInstance(result);
- WriteTo(output);
- output.CheckNoSpaceLeft();
- return result;
- }
-
- public void WriteTo(Stream output) {
- CodedOutputStream codedOutput = CodedOutputStream.CreateInstance(output);
- WriteTo(codedOutput);
- codedOutput.Flush();
- }
-
- public void WriteDelimitedTo(Stream output) {
- CodedOutputStream codedOutput = CodedOutputStream.CreateInstance(output);
- codedOutput.WriteRawVarint32((uint) SerializedSize);
- WriteTo(codedOutput);
- codedOutput.Flush();
- }
-
+ /// <summary>
+ /// Compares the specified object with this message for equality.
+ /// Returns true iff the given object is a message of the same type
+ /// (as defined by DescriptorForType) and has identical values
+ /// for all its fields.
+ /// </summary>
public override bool Equals(object other) {
if (other == this) {
return true;
@@ -226,6 +214,10 @@ namespace Google.ProtocolBuffers {
return Dictionaries.Equals(AllFields, otherMessage.AllFields) && UnknownFields.Equals(otherMessage.UnknownFields);
}
+ /// <summary>
+ /// Returns the hash code value for this message.
+ /// TODO(jonskeet): Specify the hash algorithm, but better than the Java one!
+ /// </summary>
public override int GetHashCode() {
int hash = 41;
hash = (19 * hash) + DescriptorForType.GetHashCode();
@@ -233,5 +225,21 @@ namespace Google.ProtocolBuffers {
hash = (29 * hash) + UnknownFields.GetHashCode();
return hash;
}
+
+ #region Explicit Members
+
+ IBuilder IMessage.WeakCreateBuilderForType() {
+ return CreateBuilderForType();
+ }
+
+ IBuilder IMessage.WeakToBuilder() {
+ return ToBuilder();
+ }
+
+ IMessage IMessage.WeakDefaultInstanceForType {
+ get { return DefaultInstanceForType; }
+ }
+
+ #endregion
}
}
diff --git a/src/ProtocolBuffers/AbstractMessageLite.cs b/src/ProtocolBuffers/AbstractMessageLite.cs
new file mode 100644
index 00000000..ee75f3dd
--- /dev/null
+++ b/src/ProtocolBuffers/AbstractMessageLite.cs
@@ -0,0 +1,133 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// 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.
+#endregion
+
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Google.ProtocolBuffers {
+ /// <summary>
+ /// Implementation of the non-generic IMessage interface as far as possible.
+ /// </summary>
+ public abstract class AbstractMessageLite<TMessage, TBuilder> : IMessageLite<TMessage, TBuilder>
+ where TMessage : AbstractMessageLite<TMessage, TBuilder>
+ where TBuilder : AbstractBuilderLite<TMessage, TBuilder> {
+
+
+ public abstract TBuilder CreateBuilderForType();
+
+ public abstract TBuilder ToBuilder();
+
+ public abstract TMessage DefaultInstanceForType { get; }
+
+ public abstract bool IsInitialized { get; }
+
+ public abstract void WriteTo(CodedOutputStream output);
+
+ public abstract int SerializedSize { get; }
+
+ //public override bool Equals(object other) {
+ //}
+
+ //public override int GetHashCode() {
+ //}
+
+ public abstract void PrintTo(TextWriter writer);
+
+ #region IMessageLite<TMessage,TBuilder> Members
+
+ /// <summary>
+ /// Serializes the message to a ByteString. This is a trivial wrapper
+ /// around WriteTo(CodedOutputStream).
+ /// </summary>
+ public ByteString ToByteString() {
+ ByteString.CodedBuilder output = new ByteString.CodedBuilder(SerializedSize);
+ WriteTo(output.CodedOutput);
+ return output.Build();
+ }
+
+ /// <summary>
+ /// Serializes the message to a byte array. This is a trivial wrapper
+ /// around WriteTo(CodedOutputStream).
+ /// </summary>
+ public byte[] ToByteArray() {
+ byte[] result = new byte[SerializedSize];
+ CodedOutputStream output = CodedOutputStream.CreateInstance(result);
+ WriteTo(output);
+ output.CheckNoSpaceLeft();
+ return result;
+ }
+
+ /// <summary>
+ /// Serializes the message and writes it to the given stream.
+ /// This is just a wrapper around WriteTo(CodedOutputStream). This
+ /// does not flush or close the stream.
+ /// </summary>
+ /// <param name="output"></param>
+ public void WriteTo(Stream output) {
+ CodedOutputStream codedOutput = CodedOutputStream.CreateInstance(output);
+ WriteTo(codedOutput);
+ codedOutput.Flush();
+ }
+
+ /// <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>
+ public void WriteDelimitedTo(Stream output) {
+ CodedOutputStream codedOutput = CodedOutputStream.CreateInstance(output);
+ codedOutput.WriteRawVarint32((uint)SerializedSize);
+ WriteTo(codedOutput);
+ codedOutput.Flush();
+ }
+
+ IBuilderLite IMessageLite.WeakCreateBuilderForType() {
+ return CreateBuilderForType();
+ }
+
+ IBuilderLite IMessageLite.WeakToBuilder() {
+ return ToBuilder();
+ }
+
+ IMessageLite IMessageLite.WeakDefaultInstanceForType {
+ get { return DefaultInstanceForType; }
+ }
+
+ #endregion
+ }
+}
diff --git a/src/ProtocolBuffers/ByteString.cs b/src/ProtocolBuffers/ByteString.cs
index 78b946bb..5add171e 100644
--- a/src/ProtocolBuffers/ByteString.cs
+++ b/src/ProtocolBuffers/ByteString.cs
@@ -79,6 +79,13 @@ namespace Google.ProtocolBuffers {
}
/// <summary>
+ /// Constructs a ByteString from the Base64 Encoded String.
+ /// </summary>
+ public static ByteString FromBase64(string bytes) {
+ return new ByteString(System.Convert.FromBase64String(bytes));
+ }
+
+ /// <summary>
/// Constructs a ByteString from the given array. The contents
/// are copied, so further modifications to the array will not
/// be reflected in the returned ByteString.
diff --git a/src/ProtocolBuffers/CodedInputStream.cs b/src/ProtocolBuffers/CodedInputStream.cs
index 3306f309..922957f2 100644
--- a/src/ProtocolBuffers/CodedInputStream.cs
+++ b/src/ProtocolBuffers/CodedInputStream.cs
@@ -258,7 +258,7 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// Reads a group field value from the stream.
/// </summary>
- public void ReadGroup(int fieldNumber, IBuilder builder,
+ public void ReadGroup(int fieldNumber, IBuilderLite builder,
ExtensionRegistry extensionRegistry) {
if (recursionDepth >= recursionLimit) {
throw InvalidProtocolBufferException.RecursionLimitExceeded();
@@ -273,12 +273,14 @@ namespace Google.ProtocolBuffers {
/// Reads a group field value from the stream and merges it into the given
/// UnknownFieldSet.
/// </summary>
- public void ReadUnknownGroup(int fieldNumber, UnknownFieldSet.Builder builder) {
+ [Obsolete]
+ public void ReadUnknownGroup(int fieldNumber, IBuilderLite builder)
+ {
if (recursionDepth >= recursionLimit) {
throw InvalidProtocolBufferException.RecursionLimitExceeded();
}
++recursionDepth;
- builder.MergeFrom(this);
+ builder.WeakMergeFrom(this);
CheckLastTagWas(WireFormat.MakeTag(fieldNumber, WireFormat.WireType.EndGroup));
--recursionDepth;
}
@@ -286,7 +288,7 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// Reads an embedded message field value from the stream.
/// </summary>
- public void ReadMessage(IBuilder builder, ExtensionRegistry extensionRegistry) {
+ public void ReadMessage(IBuilderLite builder, ExtensionRegistry extensionRegistry) {
int length = (int) ReadRawVarint32();
if (recursionDepth >= recursionLimit) {
throw InvalidProtocolBufferException.RecursionLimitExceeded();
@@ -393,7 +395,6 @@ namespace Google.ProtocolBuffers {
throw new ArgumentOutOfRangeException("Invalid field type " + fieldType);
}
}
-
#endregion
#region Underlying reading primitives
diff --git a/src/ProtocolBuffers/CodedOutputStream.cs b/src/ProtocolBuffers/CodedOutputStream.cs
index a7e1eca6..264ca6ef 100644
--- a/src/ProtocolBuffers/CodedOutputStream.cs
+++ b/src/ProtocolBuffers/CodedOutputStream.cs
@@ -206,19 +206,20 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// Writes a group field value, including tag, to the stream.
/// </summary>
- public void WriteGroup(int fieldNumber, IMessage value) {
+ public void WriteGroup(int fieldNumber, IMessageLite value) {
WriteTag(fieldNumber, WireFormat.WireType.StartGroup);
value.WriteTo(this);
WriteTag(fieldNumber, WireFormat.WireType.EndGroup);
}
- public void WriteUnknownGroup(int fieldNumber, UnknownFieldSet value) {
+ [Obsolete]
+ public void WriteUnknownGroup(int fieldNumber, IMessageLite value) {
WriteTag(fieldNumber, WireFormat.WireType.StartGroup);
value.WriteTo(this);
WriteTag(fieldNumber, WireFormat.WireType.EndGroup);
}
- public void WriteMessage(int fieldNumber, IMessage value) {
+ public void WriteMessage(int fieldNumber, IMessageLite value) {
WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
WriteRawVarint32((uint)value.SerializedSize);
value.WriteTo(this);
@@ -263,7 +264,7 @@ namespace Google.ProtocolBuffers {
WriteRawVarint64(EncodeZigZag64(value));
}
- public void WriteMessageSetExtension(int fieldNumber, IMessage value) {
+ public void WriteMessageSetExtension(int fieldNumber, IMessageLite value) {
WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.StartGroup);
WriteUInt32(WireFormat.MessageSetField.TypeID, (uint)fieldNumber);
WriteMessage(WireFormat.MessageSetField.Message, value);
@@ -288,15 +289,15 @@ namespace Google.ProtocolBuffers {
case FieldType.Fixed32: WriteFixed32(fieldNumber, (uint)value); break;
case FieldType.Bool: WriteBool(fieldNumber, (bool)value); break;
case FieldType.String: WriteString(fieldNumber, (string)value); break;
- case FieldType.Group: WriteGroup(fieldNumber, (IMessage)value); break;
- case FieldType.Message: WriteMessage(fieldNumber, (IMessage)value); break;
+ case FieldType.Group: WriteGroup(fieldNumber, (IMessageLite)value); break;
+ case FieldType.Message: WriteMessage(fieldNumber, (IMessageLite)value); break;
case FieldType.Bytes: WriteBytes(fieldNumber, (ByteString)value); break;
case FieldType.UInt32: WriteUInt32(fieldNumber, (uint)value); break;
case FieldType.SFixed32: WriteSFixed32(fieldNumber, (int)value); break;
case FieldType.SFixed64: WriteSFixed64(fieldNumber, (long)value); break;
case FieldType.SInt32: WriteSInt32(fieldNumber, (int)value); break;
case FieldType.SInt64: WriteSInt64(fieldNumber, (long)value); break;
- case FieldType.Enum: WriteEnum(fieldNumber, ((EnumValueDescriptor)value).Number);
+ case FieldType.Enum: WriteEnum(fieldNumber, ((IEnumLite)value).Number);
break;
}
}
@@ -312,15 +313,15 @@ namespace Google.ProtocolBuffers {
case FieldType.Fixed32: WriteFixed32NoTag((uint)value); break;
case FieldType.Bool: WriteBoolNoTag((bool)value); break;
case FieldType.String: WriteStringNoTag((string)value); break;
- case FieldType.Group: WriteGroupNoTag((IMessage)value); break;
- case FieldType.Message: WriteMessageNoTag((IMessage)value); break;
+ case FieldType.Group: WriteGroupNoTag((IMessageLite)value); break;
+ case FieldType.Message: WriteMessageNoTag((IMessageLite)value); break;
case FieldType.Bytes: WriteBytesNoTag((ByteString)value); break;
case FieldType.UInt32: WriteUInt32NoTag((uint)value); break;
case FieldType.SFixed32: WriteSFixed32NoTag((int)value); break;
case FieldType.SFixed64: WriteSFixed64NoTag((long)value); break;
case FieldType.SInt32: WriteSInt32NoTag((int)value); break;
case FieldType.SInt64: WriteSInt64NoTag((long)value); break;
- case FieldType.Enum: WriteEnumNoTag(((EnumValueDescriptor)value).Number);
+ case FieldType.Enum: WriteEnumNoTag(((IEnumLite)value).Number);
break;
}
}
@@ -420,11 +421,11 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// Writes a group field value, without a tag, to the stream.
/// </summary>
- public void WriteGroupNoTag(IMessage value) {
+ public void WriteGroupNoTag(IMessageLite value) {
value.WriteTo(this);
}
- public void WriteMessageNoTag(IMessage value) {
+ public void WriteMessageNoTag(IMessageLite value) {
WriteRawVarint32((uint)value.SerializedSize);
value.WriteTo(this);
}
@@ -685,7 +686,7 @@ namespace Google.ProtocolBuffers {
/// Compute the number of bytes that would be needed to encode a
/// group field, including the tag.
/// </summary>
- public static int ComputeGroupSize(int fieldNumber, IMessage value) {
+ public static int ComputeGroupSize(int fieldNumber, IMessageLite value) {
return ComputeTagSize(fieldNumber) * 2 + value.SerializedSize;
}
@@ -693,8 +694,9 @@ namespace Google.ProtocolBuffers {
/// Compute the number of bytes that would be needed to encode a
/// group field represented by an UnknownFieldSet, including the tag.
/// </summary>
+ [Obsolete]
public static int ComputeUnknownGroupSize(int fieldNumber,
- UnknownFieldSet value) {
+ IMessageLite value) {
return ComputeTagSize(fieldNumber) * 2 + value.SerializedSize;
}
@@ -702,7 +704,7 @@ namespace Google.ProtocolBuffers {
/// Compute the number of bytes that would be needed to encode an
/// embedded message field, including the tag.
/// </summary>
- public static int ComputeMessageSize(int fieldNumber, IMessage value) {
+ public static int ComputeMessageSize(int fieldNumber, IMessageLite value) {
int size = value.SerializedSize;
return ComputeTagSize(fieldNumber) + ComputeRawVarint32Size((uint)size) + size;
}
@@ -853,7 +855,7 @@ namespace Google.ProtocolBuffers {
/// Compute the number of bytes that would be needed to encode a
/// group field, including the tag.
/// </summary>
- public static int ComputeGroupSizeNoTag(IMessage value) {
+ public static int ComputeGroupSizeNoTag(IMessageLite value) {
return value.SerializedSize;
}
@@ -861,7 +863,8 @@ namespace Google.ProtocolBuffers {
/// Compute the number of bytes that would be needed to encode a
/// group field represented by an UnknownFieldSet, including the tag.
/// </summary>
- public static int ComputeUnknownGroupSizeNoTag(UnknownFieldSet value) {
+ [Obsolete]
+ public static int ComputeUnknownGroupSizeNoTag(IMessageLite value) {
return value.SerializedSize;
}
@@ -869,7 +872,7 @@ namespace Google.ProtocolBuffers {
/// Compute the number of bytes that would be needed to encode an
/// embedded message field, including the tag.
/// </summary>
- public static int ComputeMessageSizeNoTag(IMessage value) {
+ public static int ComputeMessageSizeNoTag(IMessageLite value) {
int size = value.SerializedSize;
return ComputeRawVarint32Size((uint)size) + size;
}
@@ -943,7 +946,7 @@ namespace Google.ProtocolBuffers {
/// MessageSet extension to the stream. For historical reasons,
/// the wire format differs from normal fields.
/// </summary>
- public static int ComputeMessageSetExtensionSize(int fieldNumber, IMessage value) {
+ public static int ComputeMessageSetExtensionSize(int fieldNumber, IMessageLite value) {
return ComputeTagSize(WireFormat.MessageSetField.Item) * 2 +
ComputeUInt32Size(WireFormat.MessageSetField.TypeID, (uint) fieldNumber) +
ComputeMessageSize(WireFormat.MessageSetField.Message, value);
@@ -1004,15 +1007,15 @@ namespace Google.ProtocolBuffers {
case FieldType.Fixed32: return ComputeFixed32Size(fieldNumber, (uint)value);
case FieldType.Bool: return ComputeBoolSize(fieldNumber, (bool)value);
case FieldType.String: return ComputeStringSize(fieldNumber, (string)value);
- case FieldType.Group: return ComputeGroupSize(fieldNumber, (IMessage)value);
- case FieldType.Message: return ComputeMessageSize(fieldNumber, (IMessage)value);
+ case FieldType.Group: return ComputeGroupSize(fieldNumber, (IMessageLite)value);
+ case FieldType.Message: return ComputeMessageSize(fieldNumber, (IMessageLite)value);
case FieldType.Bytes: return ComputeBytesSize(fieldNumber, (ByteString)value);
case FieldType.UInt32: return ComputeUInt32Size(fieldNumber, (uint)value);
case FieldType.SFixed32: return ComputeSFixed32Size(fieldNumber, (int)value);
case FieldType.SFixed64: return ComputeSFixed64Size(fieldNumber, (long)value);
case FieldType.SInt32: return ComputeSInt32Size(fieldNumber, (int)value);
case FieldType.SInt64: return ComputeSInt64Size(fieldNumber, (long)value);
- case FieldType.Enum: return ComputeEnumSize(fieldNumber, ((EnumValueDescriptor)value).Number);
+ case FieldType.Enum: return ComputeEnumSize(fieldNumber, ((IEnumLite)value).Number);
default:
throw new ArgumentOutOfRangeException("Invalid field type " + fieldType);
}
@@ -1033,15 +1036,15 @@ namespace Google.ProtocolBuffers {
case FieldType.Fixed32: return ComputeFixed32SizeNoTag((uint)value);
case FieldType.Bool: return ComputeBoolSizeNoTag((bool)value);
case FieldType.String: return ComputeStringSizeNoTag((string)value);
- case FieldType.Group: return ComputeGroupSizeNoTag((IMessage)value);
- case FieldType.Message: return ComputeMessageSizeNoTag((IMessage)value);
+ case FieldType.Group: return ComputeGroupSizeNoTag((IMessageLite)value);
+ case FieldType.Message: return ComputeMessageSizeNoTag((IMessageLite)value);
case FieldType.Bytes: return ComputeBytesSizeNoTag((ByteString)value);
case FieldType.UInt32: return ComputeUInt32SizeNoTag((uint)value);
case FieldType.SFixed32: return ComputeSFixed32SizeNoTag((int)value);
case FieldType.SFixed64: return ComputeSFixed64SizeNoTag((long)value);
case FieldType.SInt32: return ComputeSInt32SizeNoTag((int)value);
case FieldType.SInt64: return ComputeSInt64SizeNoTag((long)value);
- case FieldType.Enum: return ComputeEnumSizeNoTag(((EnumValueDescriptor)value).Number);
+ case FieldType.Enum: return ComputeEnumSizeNoTag(((IEnumLite)value).Number);
default:
throw new ArgumentOutOfRangeException("Invalid field type " + fieldType);
}
diff --git a/src/ProtocolBuffers/DescriptorProtos/CSharpOptions.cs b/src/ProtocolBuffers/DescriptorProtos/CSharpOptions.cs
index ae13b5ac..61d52fdc 100644
--- a/src/ProtocolBuffers/DescriptorProtos/CSharpOptions.cs
+++ b/src/ProtocolBuffers/DescriptorProtos/CSharpOptions.cs
@@ -1,4 +1,4 @@
-// Generated by the protocol buffer compiler. DO NOT EDIT!
+// Generated by ProtoGen, Version=0.9.0.0, Culture=neutral, PublicKeyToken=8fd7408b07f8d2cd. DO NOT EDIT!
using pb = global::Google.ProtocolBuffers;
using pbc = global::Google.ProtocolBuffers.Collections;
diff --git a/src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs b/src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs
index 0c6be671..09a00c97 100644
--- a/src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs
+++ b/src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs
@@ -1,4 +1,4 @@
-// Generated by the protocol buffer compiler. DO NOT EDIT!
+// Generated by ProtoGen, Version=0.9.0.0, Culture=neutral, PublicKeyToken=8fd7408b07f8d2cd. DO NOT EDIT!
using pb = global::Google.ProtocolBuffers;
using pbc = global::Google.ProtocolBuffers.Collections;
@@ -104,38 +104,42 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
"Lmdvb2dsZS5wcm90b2J1Zi5TZXJ2aWNlT3B0aW9ucyJ/ChVNZXRob2REZXNj" +
"cmlwdG9yUHJvdG8SDAoEbmFtZRgBIAEoCRISCgppbnB1dF90eXBlGAIgASgJ" +
"EhMKC291dHB1dF90eXBlGAMgASgJEi8KB29wdGlvbnMYBCABKAsyHi5nb29n" +
- "bGUucHJvdG9idWYuTWV0aG9kT3B0aW9ucyKnAgoLRmlsZU9wdGlvbnMSFAoM" +
+ "bGUucHJvdG9idWYuTWV0aG9kT3B0aW9ucyKkAwoLRmlsZU9wdGlvbnMSFAoM" +
"amF2YV9wYWNrYWdlGAEgASgJEhwKFGphdmFfb3V0ZXJfY2xhc3NuYW1lGAgg" +
"ASgJEiIKE2phdmFfbXVsdGlwbGVfZmlsZXMYCiABKAg6BWZhbHNlEkYKDG9w" +
"dGltaXplX2ZvchgJIAEoDjIpLmdvb2dsZS5wcm90b2J1Zi5GaWxlT3B0aW9u" +
- "cy5PcHRpbWl6ZU1vZGU6BVNQRUVEEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9u" +
- "GOcHIAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9u" +
- "IigKDE9wdGltaXplTW9kZRIJCgVTUEVFRBABEg0KCUNPREVfU0laRRACKgkI" +
- "6AcQgICAgAIiiAEKDk1lc3NhZ2VPcHRpb25zEiYKF21lc3NhZ2Vfc2V0X3dp" +
- "cmVfZm9ybWF0GAEgASgIOgVmYWxzZRJDChR1bmludGVycHJldGVkX29wdGlv" +
- "bhjnByADKAsyJC5nb29nbGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9wdGlv" +
- "bioJCOgHEICAgIACIoACCgxGaWVsZE9wdGlvbnMSMgoFY3R5cGUYASABKA4y" +
- "Iy5nb29nbGUucHJvdG9idWYuRmllbGRPcHRpb25zLkNUeXBlEg4KBnBhY2tl" +
- "ZBgCIAEoCBIZCgpkZXByZWNhdGVkGAMgASgIOgVmYWxzZRIcChRleHBlcmlt" +
- "ZW50YWxfbWFwX2tleRgJIAEoCRJDChR1bmludGVycHJldGVkX29wdGlvbhjn" +
- "ByADKAsyJC5nb29nbGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9wdGlvbiIj" +
- "CgVDVHlwZRIICgRDT1JEEAESEAoMU1RSSU5HX1BJRUNFEAIqCQjoBxCAgICA" +
- "AiJdCgtFbnVtT3B0aW9ucxJDChR1bmludGVycHJldGVkX29wdGlvbhjnByAD" +
- "KAsyJC5nb29nbGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9wdGlvbioJCOgH" +
- "EICAgIACImIKEEVudW1WYWx1ZU9wdGlvbnMSQwoUdW5pbnRlcnByZXRlZF9v" +
- "cHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0ZWRP" +
- "cHRpb24qCQjoBxCAgICAAiJgCg5TZXJ2aWNlT3B0aW9ucxJDChR1bmludGVy" +
- "cHJldGVkX29wdGlvbhjnByADKAsyJC5nb29nbGUucHJvdG9idWYuVW5pbnRl" +
- "cnByZXRlZE9wdGlvbioJCOgHEICAgIACIl8KDU1ldGhvZE9wdGlvbnMSQwoU" +
- "dW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVm" +
- "LlVuaW50ZXJwcmV0ZWRPcHRpb24qCQjoBxCAgICAAiKFAgoTVW5pbnRlcnBy" +
- "ZXRlZE9wdGlvbhI7CgRuYW1lGAIgAygLMi0uZ29vZ2xlLnByb3RvYnVmLlVu" +
- "aW50ZXJwcmV0ZWRPcHRpb24uTmFtZVBhcnQSGAoQaWRlbnRpZmllcl92YWx1" +
- "ZRgDIAEoCRIaChJwb3NpdGl2ZV9pbnRfdmFsdWUYBCABKAQSGgoSbmVnYXRp" +
- "dmVfaW50X3ZhbHVlGAUgASgDEhQKDGRvdWJsZV92YWx1ZRgGIAEoARIUCgxz" +
- "dHJpbmdfdmFsdWUYByABKAwaMwoITmFtZVBhcnQSEQoJbmFtZV9wYXJ0GAEg" +
- "AigJEhQKDGlzX2V4dGVuc2lvbhgCIAIoCEIpChNjb20uZ29vZ2xlLnByb3Rv" +
- "YnVmQhBEZXNjcmlwdG9yUHJvdG9zSAE=");
+ "cy5PcHRpbWl6ZU1vZGU6BVNQRUVEEiEKE2NjX2dlbmVyaWNfc2VydmljZXMY" +
+ "ECABKAg6BHRydWUSIwoVamF2YV9nZW5lcmljX3NlcnZpY2VzGBEgASgIOgR0" +
+ "cnVlEiEKE3B5X2dlbmVyaWNfc2VydmljZXMYEiABKAg6BHRydWUSQwoUdW5p" +
+ "bnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVu" +
+ "aW50ZXJwcmV0ZWRPcHRpb24iOgoMT3B0aW1pemVNb2RlEgkKBVNQRUVEEAES" +
+ "DQoJQ09ERV9TSVpFEAISEAoMTElURV9SVU5USU1FEAMqCQjoBxCAgICAAiK4" +
+ "AQoOTWVzc2FnZU9wdGlvbnMSJgoXbWVzc2FnZV9zZXRfd2lyZV9mb3JtYXQY" +
+ "ASABKAg6BWZhbHNlEi4KH25vX3N0YW5kYXJkX2Rlc2NyaXB0b3JfYWNjZXNz" +
+ "b3IYAiABKAg6BWZhbHNlEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMo" +
+ "CzIkLmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uKgkI6AcQ" +
+ "gICAgAIilAIKDEZpZWxkT3B0aW9ucxI6CgVjdHlwZRgBIAEoDjIjLmdvb2ds" +
+ "ZS5wcm90b2J1Zi5GaWVsZE9wdGlvbnMuQ1R5cGU6BlNUUklORxIOCgZwYWNr" +
+ "ZWQYAiABKAgSGQoKZGVwcmVjYXRlZBgDIAEoCDoFZmFsc2USHAoUZXhwZXJp" +
+ "bWVudGFsX21hcF9rZXkYCSABKAkSQwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y" +
+ "5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24i" +
+ "LwoFQ1R5cGUSCgoGU1RSSU5HEAASCAoEQ09SRBABEhAKDFNUUklOR19QSUVD" +
+ "RRACKgkI6AcQgICAgAIiXQoLRW51bU9wdGlvbnMSQwoUdW5pbnRlcnByZXRl" +
+ "ZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0" +
+ "ZWRPcHRpb24qCQjoBxCAgICAAiJiChBFbnVtVmFsdWVPcHRpb25zEkMKFHVu" +
+ "aW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5V" +
+ "bmludGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAIiYAoOU2VydmljZU9wdGlv" +
+ "bnMSQwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnBy" +
+ "b3RvYnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24qCQjoBxCAgICAAiJfCg1NZXRo" +
+ "b2RPcHRpb25zEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdv" +
+ "b2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAIi" +
+ "hQIKE1VuaW50ZXJwcmV0ZWRPcHRpb24SOwoEbmFtZRgCIAMoCzItLmdvb2ds" +
+ "ZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uLk5hbWVQYXJ0EhgKEGlk" +
+ "ZW50aWZpZXJfdmFsdWUYAyABKAkSGgoScG9zaXRpdmVfaW50X3ZhbHVlGAQg" +
+ "ASgEEhoKEm5lZ2F0aXZlX2ludF92YWx1ZRgFIAEoAxIUCgxkb3VibGVfdmFs" +
+ "dWUYBiABKAESFAoMc3RyaW5nX3ZhbHVlGAcgASgMGjMKCE5hbWVQYXJ0EhEK" +
+ "CW5hbWVfcGFydBgBIAIoCRIUCgxpc19leHRlbnNpb24YAiACKAhCKQoTY29t" +
+ "Lmdvb2dsZS5wcm90b2J1ZkIQRGVzY3JpcHRvclByb3Rvc0gB");
pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) {
descriptor = root;
internal__static_google_protobuf_FileDescriptorSet__Descriptor = Descriptor.MessageTypes[0];
@@ -177,11 +181,11 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
internal__static_google_protobuf_FileOptions__Descriptor = Descriptor.MessageTypes[8];
internal__static_google_protobuf_FileOptions__FieldAccessorTable =
new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.FileOptions, global::Google.ProtocolBuffers.DescriptorProtos.FileOptions.Builder>(internal__static_google_protobuf_FileOptions__Descriptor,
- new string[] { "JavaPackage", "JavaOuterClassname", "JavaMultipleFiles", "OptimizeFor", "UninterpretedOption", });
+ new string[] { "JavaPackage", "JavaOuterClassname", "JavaMultipleFiles", "OptimizeFor", "CcGenericServices", "JavaGenericServices", "PyGenericServices", "UninterpretedOption", });
internal__static_google_protobuf_MessageOptions__Descriptor = Descriptor.MessageTypes[9];
internal__static_google_protobuf_MessageOptions__FieldAccessorTable =
new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.MessageOptions, global::Google.ProtocolBuffers.DescriptorProtos.MessageOptions.Builder>(internal__static_google_protobuf_MessageOptions__Descriptor,
- new string[] { "MessageSetWireFormat", "UninterpretedOption", });
+ new string[] { "MessageSetWireFormat", "NoStandardDescriptorAccessor", "UninterpretedOption", });
internal__static_google_protobuf_FieldOptions__Descriptor = Descriptor.MessageTypes[10];
internal__static_google_protobuf_FieldOptions__FieldAccessorTable =
new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions, global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions.Builder>(internal__static_google_protobuf_FieldOptions__Descriptor,
@@ -4013,6 +4017,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
public enum OptimizeMode {
SPEED = 1,
CODE_SIZE = 2,
+ LITE_RUNTIME = 3,
}
}
@@ -4058,6 +4063,36 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
get { return optimizeFor_; }
}
+ public const int CcGenericServicesFieldNumber = 16;
+ private bool hasCcGenericServices;
+ private bool ccGenericServices_ = true;
+ public bool HasCcGenericServices {
+ get { return hasCcGenericServices; }
+ }
+ public bool CcGenericServices {
+ get { return ccGenericServices_; }
+ }
+
+ public const int JavaGenericServicesFieldNumber = 17;
+ private bool hasJavaGenericServices;
+ private bool javaGenericServices_ = true;
+ public bool HasJavaGenericServices {
+ get { return hasJavaGenericServices; }
+ }
+ public bool JavaGenericServices {
+ get { return javaGenericServices_; }
+ }
+
+ public const int PyGenericServicesFieldNumber = 18;
+ private bool hasPyGenericServices;
+ private bool pyGenericServices_ = true;
+ public bool HasPyGenericServices {
+ get { return hasPyGenericServices; }
+ }
+ public bool PyGenericServices {
+ get { return pyGenericServices_; }
+ }
+
public const int UninterpretedOptionFieldNumber = 999;
private pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption> uninterpretedOption_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption>();
public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption> UninterpretedOptionList {
@@ -4095,6 +4130,15 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
if (HasJavaMultipleFiles) {
output.WriteBool(10, JavaMultipleFiles);
}
+ if (HasCcGenericServices) {
+ output.WriteBool(16, CcGenericServices);
+ }
+ if (HasJavaGenericServices) {
+ output.WriteBool(17, JavaGenericServices);
+ }
+ if (HasPyGenericServices) {
+ output.WriteBool(18, PyGenericServices);
+ }
foreach (global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption element in UninterpretedOptionList) {
output.WriteMessage(999, element);
}
@@ -4121,6 +4165,15 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
if (HasOptimizeFor) {
size += pb::CodedOutputStream.ComputeEnumSize(9, (int) OptimizeFor);
}
+ if (HasCcGenericServices) {
+ size += pb::CodedOutputStream.ComputeBoolSize(16, CcGenericServices);
+ }
+ if (HasJavaGenericServices) {
+ size += pb::CodedOutputStream.ComputeBoolSize(17, JavaGenericServices);
+ }
+ if (HasPyGenericServices) {
+ size += pb::CodedOutputStream.ComputeBoolSize(18, PyGenericServices);
+ }
foreach (global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption element in UninterpretedOptionList) {
size += pb::CodedOutputStream.ComputeMessageSize(999, element);
}
@@ -4230,6 +4283,15 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
if (other.HasOptimizeFor) {
OptimizeFor = other.OptimizeFor;
}
+ if (other.HasCcGenericServices) {
+ CcGenericServices = other.CcGenericServices;
+ }
+ if (other.HasJavaGenericServices) {
+ JavaGenericServices = other.JavaGenericServices;
+ }
+ if (other.HasPyGenericServices) {
+ PyGenericServices = other.PyGenericServices;
+ }
if (other.uninterpretedOption_.Count != 0) {
base.AddRange(other.uninterpretedOption_, result.uninterpretedOption_);
}
@@ -4290,6 +4352,18 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
JavaMultipleFiles = input.ReadBool();
break;
}
+ case 128: {
+ CcGenericServices = input.ReadBool();
+ break;
+ }
+ case 136: {
+ JavaGenericServices = input.ReadBool();
+ break;
+ }
+ case 144: {
+ PyGenericServices = input.ReadBool();
+ break;
+ }
case 7994: {
global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.CreateBuilder();
input.ReadMessage(subBuilder, extensionRegistry);
@@ -4375,6 +4449,60 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
return this;
}
+ public bool HasCcGenericServices {
+ get { return result.HasCcGenericServices; }
+ }
+ public bool CcGenericServices {
+ get { return result.CcGenericServices; }
+ set { SetCcGenericServices(value); }
+ }
+ public Builder SetCcGenericServices(bool value) {
+ result.hasCcGenericServices = true;
+ result.ccGenericServices_ = value;
+ return this;
+ }
+ public Builder ClearCcGenericServices() {
+ result.hasCcGenericServices = false;
+ result.ccGenericServices_ = true;
+ return this;
+ }
+
+ public bool HasJavaGenericServices {
+ get { return result.HasJavaGenericServices; }
+ }
+ public bool JavaGenericServices {
+ get { return result.JavaGenericServices; }
+ set { SetJavaGenericServices(value); }
+ }
+ public Builder SetJavaGenericServices(bool value) {
+ result.hasJavaGenericServices = true;
+ result.javaGenericServices_ = value;
+ return this;
+ }
+ public Builder ClearJavaGenericServices() {
+ result.hasJavaGenericServices = false;
+ result.javaGenericServices_ = true;
+ return this;
+ }
+
+ public bool HasPyGenericServices {
+ get { return result.HasPyGenericServices; }
+ }
+ public bool PyGenericServices {
+ get { return result.PyGenericServices; }
+ set { SetPyGenericServices(value); }
+ }
+ public Builder SetPyGenericServices(bool value) {
+ result.hasPyGenericServices = true;
+ result.pyGenericServices_ = value;
+ return this;
+ }
+ public Builder ClearPyGenericServices() {
+ result.hasPyGenericServices = false;
+ result.pyGenericServices_ = true;
+ return this;
+ }
+
public pbc::IPopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption> UninterpretedOptionList {
get { return result.uninterpretedOption_; }
}
@@ -4450,6 +4578,16 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
get { return messageSetWireFormat_; }
}
+ public const int NoStandardDescriptorAccessorFieldNumber = 2;
+ private bool hasNoStandardDescriptorAccessor;
+ private bool noStandardDescriptorAccessor_ = false;
+ public bool HasNoStandardDescriptorAccessor {
+ get { return hasNoStandardDescriptorAccessor; }
+ }
+ public bool NoStandardDescriptorAccessor {
+ get { return noStandardDescriptorAccessor_; }
+ }
+
public const int UninterpretedOptionFieldNumber = 999;
private pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption> uninterpretedOption_ = new pbc::PopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption>();
public scg::IList<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption> UninterpretedOptionList {
@@ -4478,6 +4616,9 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
if (HasMessageSetWireFormat) {
output.WriteBool(1, MessageSetWireFormat);
}
+ if (HasNoStandardDescriptorAccessor) {
+ output.WriteBool(2, NoStandardDescriptorAccessor);
+ }
foreach (global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption element in UninterpretedOptionList) {
output.WriteMessage(999, element);
}
@@ -4495,6 +4636,9 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
if (HasMessageSetWireFormat) {
size += pb::CodedOutputStream.ComputeBoolSize(1, MessageSetWireFormat);
}
+ if (HasNoStandardDescriptorAccessor) {
+ size += pb::CodedOutputStream.ComputeBoolSize(2, NoStandardDescriptorAccessor);
+ }
foreach (global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption element in UninterpretedOptionList) {
size += pb::CodedOutputStream.ComputeMessageSize(999, element);
}
@@ -4595,6 +4739,9 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
if (other.HasMessageSetWireFormat) {
MessageSetWireFormat = other.MessageSetWireFormat;
}
+ if (other.HasNoStandardDescriptorAccessor) {
+ NoStandardDescriptorAccessor = other.NoStandardDescriptorAccessor;
+ }
if (other.uninterpretedOption_.Count != 0) {
base.AddRange(other.uninterpretedOption_, result.uninterpretedOption_);
}
@@ -4635,6 +4782,10 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
MessageSetWireFormat = input.ReadBool();
break;
}
+ case 16: {
+ NoStandardDescriptorAccessor = input.ReadBool();
+ break;
+ }
case 7994: {
global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.Builder subBuilder = global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption.CreateBuilder();
input.ReadMessage(subBuilder, extensionRegistry);
@@ -4664,6 +4815,24 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
return this;
}
+ public bool HasNoStandardDescriptorAccessor {
+ get { return result.HasNoStandardDescriptorAccessor; }
+ }
+ public bool NoStandardDescriptorAccessor {
+ get { return result.NoStandardDescriptorAccessor; }
+ set { SetNoStandardDescriptorAccessor(value); }
+ }
+ public Builder SetNoStandardDescriptorAccessor(bool value) {
+ result.hasNoStandardDescriptorAccessor = true;
+ result.noStandardDescriptorAccessor_ = value;
+ return this;
+ }
+ public Builder ClearNoStandardDescriptorAccessor() {
+ result.hasNoStandardDescriptorAccessor = false;
+ result.noStandardDescriptorAccessor_ = false;
+ return this;
+ }
+
public pbc::IPopsicleList<global::Google.ProtocolBuffers.DescriptorProtos.UninterpretedOption> UninterpretedOptionList {
get { return result.uninterpretedOption_; }
}
@@ -4732,6 +4901,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
#region Nested types
public static class Types {
public enum CType {
+ STRING = 0,
CORD = 1,
STRING_PIECE = 2,
}
@@ -4741,7 +4911,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
public const int CtypeFieldNumber = 1;
private bool hasCtype;
- private global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions.Types.CType ctype_ = global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions.Types.CType.CORD;
+ private global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions.Types.CType ctype_ = global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions.Types.CType.STRING;
public bool HasCtype {
get { return hasCtype; }
}
@@ -5036,7 +5206,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
}
public Builder ClearCtype() {
result.hasCtype = false;
- result.ctype_ = global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions.Types.CType.CORD;
+ result.ctype_ = global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions.Types.CType.STRING;
return this;
}
diff --git a/src/ProtocolBuffers/Descriptors/EnumDescriptor.cs b/src/ProtocolBuffers/Descriptors/EnumDescriptor.cs
index 2fa18d9a..d6ef4e17 100644
--- a/src/ProtocolBuffers/Descriptors/EnumDescriptor.cs
+++ b/src/ProtocolBuffers/Descriptors/EnumDescriptor.cs
@@ -37,7 +37,7 @@ namespace Google.ProtocolBuffers.Descriptors {
/// <summary>
/// Descriptor for an enum type in a .proto file.
/// </summary>
- public sealed class EnumDescriptor : IndexedDescriptorBase<EnumDescriptorProto, EnumOptions> {
+ public sealed class EnumDescriptor : IndexedDescriptorBase<EnumDescriptorProto, EnumOptions>, IEnumLiteMap<EnumValueDescriptor> {
private readonly MessageDescriptor containingType;
private readonly IList<EnumValueDescriptor> values;
@@ -73,13 +73,23 @@ namespace Google.ProtocolBuffers.Descriptors {
}
/// <summary>
+ /// Logic moved from FieldSet to continue current behavior
+ /// </summary>
+ public bool IsValidValue(IEnumLite value) {
+ return value is EnumValueDescriptor && ((EnumValueDescriptor)value).EnumDescriptor == this;
+ }
+
+ /// <summary>
/// Finds an enum value by number. If multiple enum values have the
/// same number, this returns the first defined value with that number.
/// </summary>
- internal EnumValueDescriptor FindValueByNumber(int number) {
+ public EnumValueDescriptor FindValueByNumber(int number) {
return File.DescriptorPool.FindEnumValueByNumber(this, number);
}
+ IEnumLite IEnumLiteMap.FindValueByNumber(int number) {
+ return FindValueByNumber(number);
+ }
/// <summary>
/// Finds an enum value by name.
/// </summary>
diff --git a/src/ProtocolBuffers/Descriptors/EnumValueDescriptor.cs b/src/ProtocolBuffers/Descriptors/EnumValueDescriptor.cs
index 4125814d..732dec06 100644
--- a/src/ProtocolBuffers/Descriptors/EnumValueDescriptor.cs
+++ b/src/ProtocolBuffers/Descriptors/EnumValueDescriptor.cs
@@ -36,7 +36,7 @@ namespace Google.ProtocolBuffers.Descriptors {
/// <summary>
/// Descriptor for a single enum value within an enum in a .proto file.
/// </summary>
- public sealed class EnumValueDescriptor : IndexedDescriptorBase<EnumValueDescriptorProto, EnumValueOptions> {
+ public sealed class EnumValueDescriptor : IndexedDescriptorBase<EnumValueDescriptorProto, EnumValueOptions>, IEnumLite {
private readonly EnumDescriptor enumDescriptor;
diff --git a/src/ProtocolBuffers/Descriptors/FieldDescriptor.cs b/src/ProtocolBuffers/Descriptors/FieldDescriptor.cs
index 7d99ed21..854b3a89 100644
--- a/src/ProtocolBuffers/Descriptors/FieldDescriptor.cs
+++ b/src/ProtocolBuffers/Descriptors/FieldDescriptor.cs
@@ -40,7 +40,7 @@ namespace Google.ProtocolBuffers.Descriptors {
/// <summary>
/// Descriptor for a field or extension within a message in a .proto file.
/// </summary>
- public sealed class FieldDescriptor : IndexedDescriptorBase<FieldDescriptorProto, FieldOptions>, IComparable<FieldDescriptor> {
+ public sealed class FieldDescriptor : IndexedDescriptorBase<FieldDescriptorProto, FieldOptions>, IComparable<FieldDescriptor>, IFieldDescriptorLite {
private readonly MessageDescriptor extensionScope;
private EnumDescriptor enumType;
@@ -299,9 +299,26 @@ namespace Google.ProtocolBuffers.Descriptors {
}
return FieldNumber - other.FieldNumber;
}
-
/// <summary>
+ /// Compares this descriptor with another one, ordering in "canonical" order
+ /// which simply means ascending order by field number. <paramref name="other"/>
+ /// must be a field of the same type, i.e. the <see cref="ContainingType"/> of
+ /// both fields must be the same.
+ /// </summary>
+ public int CompareTo(IFieldDescriptorLite other) {
+ return FieldNumber - other.FieldNumber;
+ }
+
+ IEnumLiteMap IFieldDescriptorLite.EnumType {
+ get { return EnumType; }
+ }
+
+ bool IFieldDescriptorLite.MessageSetWireFormat {
+ get { return ContainingType.Options.MessageSetWireFormat; }
+ }
+
+ /// <summary>
/// For enum fields, returns the field's type.
/// </summary>
public EnumDescriptor EnumType {
diff --git a/src/ProtocolBuffers/Descriptors/FieldMappingAttribute.cs b/src/ProtocolBuffers/Descriptors/FieldMappingAttribute.cs
index e62360fc..b0bf5de1 100644
--- a/src/ProtocolBuffers/Descriptors/FieldMappingAttribute.cs
+++ b/src/ProtocolBuffers/Descriptors/FieldMappingAttribute.cs
@@ -30,6 +30,8 @@
// (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;
+using System.Collections.Generic;
+using Google.ProtocolBuffers.Collections;
namespace Google.ProtocolBuffers.Descriptors {
@@ -46,5 +48,29 @@ namespace Google.ProtocolBuffers.Descriptors {
internal MappedType MappedType { get; private set; }
internal WireFormat.WireType WireType { get; private set; }
+
+
+ /// <summary>
+ /// Immutable mapping from field type to mapped type. Built using the attributes on
+ /// FieldType values.
+ /// </summary>
+ static readonly IDictionary<FieldType, FieldMappingAttribute> FieldTypeToMappedTypeMap = MapFieldTypes();
+
+ private static IDictionary<FieldType, FieldMappingAttribute> MapFieldTypes() {
+ var map = new Dictionary<FieldType, FieldMappingAttribute>();
+ foreach (System.Reflection.FieldInfo field in typeof(FieldType).GetFields(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public)) {
+ FieldType fieldType = (FieldType)field.GetValue(null);
+ FieldMappingAttribute mapping = (FieldMappingAttribute)field.GetCustomAttributes(typeof(FieldMappingAttribute), false)[0];
+ map[fieldType] = mapping;
+ }
+ return Dictionaries.AsReadOnly(map);
+ }
+
+ internal static MappedType MappedTypeFromFieldType(FieldType type) {
+ return FieldTypeToMappedTypeMap[type].MappedType;
+ }
+ internal static WireFormat.WireType WireTypeFromFieldType(FieldType type, bool packed) {
+ return packed ? WireFormat.WireType.LengthDelimited : FieldTypeToMappedTypeMap[type].WireType;
+ }
}
}
diff --git a/src/ProtocolBuffers/DynamicMessage.cs b/src/ProtocolBuffers/DynamicMessage.cs
index 12f2186c..44fe0f39 100644
--- a/src/ProtocolBuffers/DynamicMessage.cs
+++ b/src/ProtocolBuffers/DynamicMessage.cs
@@ -180,7 +180,7 @@ namespace Google.ProtocolBuffers {
}
public override IDictionary<FieldDescriptor, object> AllFields {
- get { return fields.AllFields; }
+ get { return fields.AllFieldDescriptors; }
}
public override bool HasField(FieldDescriptor field) {
@@ -216,7 +216,7 @@ namespace Google.ProtocolBuffers {
}
public bool Initialized {
- get { return fields.IsInitializedWithRespectTo(type); }
+ get { return fields.IsInitializedWithRespectTo(type.Fields); }
}
public override void WriteTo(CodedOutputStream output) {
@@ -295,7 +295,8 @@ namespace Google.ProtocolBuffers {
}
public override Builder MergeFrom(DynamicMessage other) {
- return MergeFrom((IMessage)other);
+ IMessage downcast = other;
+ return MergeFrom(downcast);
}
public override DynamicMessage Build() {
@@ -335,7 +336,7 @@ namespace Google.ProtocolBuffers {
}
public override bool IsInitialized {
- get { return fields.IsInitializedWithRespectTo(type); }
+ get { return fields.IsInitializedWithRespectTo(type.Fields); }
}
public override Builder MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry) {
@@ -354,7 +355,7 @@ namespace Google.ProtocolBuffers {
}
public override IDictionary<FieldDescriptor, object> AllFields {
- get { return fields.AllFields; }
+ get { return fields.AllFieldDescriptors; }
}
public override IBuilder CreateBuilderForField(FieldDescriptor field) {
diff --git a/src/ProtocolBuffers/EnumLite.cs b/src/ProtocolBuffers/EnumLite.cs
new file mode 100644
index 00000000..12497d8e
--- /dev/null
+++ b/src/ProtocolBuffers/EnumLite.cs
@@ -0,0 +1,106 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// 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.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Text;
+
+namespace Google.ProtocolBuffers {
+
+ ///<summary>
+ ///Interface for an enum value or value descriptor, to be used in FieldSet.
+ ///The lite library stores enum values directly in FieldSets but the full
+ ///library stores EnumValueDescriptors in order to better support reflection.
+ ///</summary>
+ public interface IEnumLite {
+ int Number { get; }
+ string Name { get; }
+ }
+
+ ///<summary>
+ ///Interface for an object which maps integers to {@link EnumLite}s.
+ ///{@link Descriptors.EnumDescriptor} implements this interface by mapping
+ ///numbers to {@link Descriptors.EnumValueDescriptor}s. Additionally,
+ ///every generated enum type has a static method internalGetValueMap() which
+ ///returns an implementation of this type that maps numbers to enum values.
+ ///</summary>
+ public interface IEnumLiteMap<T> : IEnumLiteMap
+ where T : IEnumLite {
+ new T FindValueByNumber(int number);
+ }
+
+ public interface IEnumLiteMap {
+ bool IsValidValue(IEnumLite value);
+ IEnumLite FindValueByNumber(int number);
+ }
+
+ public class EnumLiteMap<TEnum> : IEnumLiteMap<IEnumLite>
+ where TEnum : struct, IComparable, IFormattable {
+
+ struct EnumValue : IEnumLite {
+ readonly TEnum value;
+ public EnumValue(TEnum value) {
+ this.value = value;
+ }
+ int IEnumLite.Number {
+ get { return Convert.ToInt32(value); }
+ }
+ string IEnumLite.Name {
+ get { return value.ToString(); }
+ }
+ }
+
+ private readonly SortedList<int, IEnumLite> items;
+
+ public EnumLiteMap() {
+ items = new SortedList<int, IEnumLite>();
+ foreach (TEnum evalue in Enum.GetValues(typeof(TEnum)))
+ items.Add(Convert.ToInt32(evalue), new EnumValue(evalue));
+ }
+
+ IEnumLite IEnumLiteMap.FindValueByNumber(int number) {
+ return FindValueByNumber(number);
+ }
+
+ public IEnumLite FindValueByNumber(int number) {
+ IEnumLite val;
+ return items.TryGetValue(number, out val) ? val : null;
+ }
+
+ public bool IsValidValue(IEnumLite value) {
+ return items.ContainsKey(value.Number);
+ }
+ }
+}
diff --git a/src/ProtocolBuffers/ExtendableBuilder.cs b/src/ProtocolBuffers/ExtendableBuilder.cs
index 803ceb1e..ad97cdc4 100644
--- a/src/ProtocolBuffers/ExtendableBuilder.cs
+++ b/src/ProtocolBuffers/ExtendableBuilder.cs
@@ -94,21 +94,21 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// Appends a value to a repeated extension.
/// </summary>
- public ExtendableBuilder<TMessage, TBuilder> AddExtension<TExtension>(GeneratedExtensionBase<IList<TExtension>> extension, TExtension value) {
+ public TBuilder AddExtension<TExtension>(GeneratedExtensionBase<IList<TExtension>> extension, TExtension value) {
ExtendableMessage<TMessage, TBuilder> message = MessageBeingBuilt;
message.VerifyExtensionContainingType(extension);
message.Extensions.AddRepeatedField(extension.Descriptor, extension.SingularToReflectionType(value));
- return this;
+ return ThisBuilder;
}
/// <summary>
/// Clears an extension.
/// </summary>
- public ExtendableBuilder<TMessage, TBuilder> ClearExtension<TExtension>(GeneratedExtensionBase<TExtension> extension) {
+ public TBuilder ClearExtension<TExtension>(GeneratedExtensionBase<TExtension> extension) {
ExtendableMessage<TMessage, TBuilder> message = MessageBeingBuilt;
message.VerifyExtensionContainingType(extension);
message.Extensions.ClearField(extension.Descriptor);
- return this;
+ return ThisBuilder;
}
/// <summary>
diff --git a/src/ProtocolBuffers/ExtendableBuilderLite.cs b/src/ProtocolBuffers/ExtendableBuilderLite.cs
new file mode 100644
index 00000000..b3d37eda
--- /dev/null
+++ b/src/ProtocolBuffers/ExtendableBuilderLite.cs
@@ -0,0 +1,262 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// 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.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using Google.ProtocolBuffers.Descriptors;
+
+namespace Google.ProtocolBuffers {
+ public abstract class ExtendableBuilderLite<TMessage, TBuilder> : GeneratedBuilderLite<TMessage, TBuilder>
+ where TMessage : ExtendableMessageLite<TMessage, TBuilder>
+ where TBuilder : GeneratedBuilderLite<TMessage, TBuilder> {
+
+ protected ExtendableBuilderLite() { }
+
+ /// <summary>
+ /// Checks if a singular extension is present
+ /// </summary>
+ public bool HasExtension<TExtension>(GeneratedExtensionLite<TMessage, TExtension> extension) {
+ return MessageBeingBuilt.HasExtension(extension);
+ }
+
+ /// <summary>
+ /// Returns the number of elements in a repeated extension.
+ /// </summary>
+ public int GetExtensionCount<TExtension>(GeneratedExtensionLite<TMessage, IList<TExtension>> extension) {
+ return MessageBeingBuilt.GetExtensionCount(extension);
+ }
+
+ /// <summary>
+ /// Returns the value of an extension.
+ /// </summary>
+ public TExtension GetExtension<TExtension>(GeneratedExtensionLite<TMessage, TExtension> extension) {
+ return MessageBeingBuilt.GetExtension(extension);
+ }
+
+ /// <summary>
+ /// Returns one element of a repeated extension.
+ /// </summary>
+ public TExtension GetExtension<TExtension>(GeneratedExtensionLite<TMessage, IList<TExtension>> extension, int index) {
+ return MessageBeingBuilt.GetExtension(extension, index);
+ }
+
+ /// <summary>
+ /// Sets the value of an extension.
+ /// </summary>
+ public TBuilder SetExtension<TExtension>(GeneratedExtensionLite<TMessage, TExtension> extension, TExtension value) {
+ ExtendableMessageLite<TMessage, TBuilder> message = MessageBeingBuilt;
+ message.VerifyExtensionContainingType(extension);
+ message.Extensions[extension.Descriptor] = extension.ToReflectionType(value);
+ return ThisBuilder;
+ }
+
+ /// <summary>
+ /// Sets the value of one element of a repeated extension.
+ /// </summary>
+ public TBuilder SetExtension<TExtension>(GeneratedExtensionLite<TMessage, IList<TExtension>> extension, int index, TExtension value) {
+ ExtendableMessageLite<TMessage, TBuilder> message = MessageBeingBuilt;
+ message.VerifyExtensionContainingType(extension);
+ message.Extensions[extension.Descriptor, index] = extension.SingularToReflectionType(value);
+ return ThisBuilder;
+ }
+
+ /// <summary>
+ /// Appends a value to a repeated extension.
+ /// </summary>
+ public TBuilder AddExtension<TExtension>(GeneratedExtensionLite<TMessage, IList<TExtension>> extension, TExtension value) {
+ ExtendableMessageLite<TMessage, TBuilder> message = MessageBeingBuilt;
+ message.VerifyExtensionContainingType(extension);
+ message.Extensions.AddRepeatedField(extension.Descriptor, extension.SingularToReflectionType(value));
+ return ThisBuilder;
+ }
+
+ /// <summary>
+ /// Clears an extension.
+ /// </summary>
+ public TBuilder ClearExtension<TExtension>(GeneratedExtensionLite<TMessage, TExtension> extension) {
+ ExtendableMessageLite<TMessage, TBuilder> message = MessageBeingBuilt;
+ message.VerifyExtensionContainingType(extension);
+ message.Extensions.ClearField(extension.Descriptor);
+ return ThisBuilder;
+ }
+
+ /// <summary>
+ /// Called by subclasses to parse an unknown field or an extension.
+ /// </summary>
+ /// <returns>true unless the tag is an end-group tag</returns>
+ [CLSCompliant(false)]
+ protected override bool ParseUnknownField(CodedInputStream input,
+ ExtensionRegistry extensionRegistry, uint tag) {
+ FieldSet extensions = MessageBeingBuilt.Extensions;
+
+ WireFormat.WireType wireType = WireFormat.GetTagWireType(tag);
+ int fieldNumber = WireFormat.GetTagFieldNumber(tag);
+ IGeneratedExtensionLite extension = extensionRegistry[DefaultInstanceForType, fieldNumber];
+
+ bool unknown = false;
+ bool packed = false;
+ if (extension == null) {
+ unknown = true; // Unknown field.
+ } else if (wireType == FieldMappingAttribute.WireTypeFromFieldType(extension.Descriptor.FieldType, false /* isPacked */)) {
+ packed = false; // Normal, unpacked value.
+ } else if (extension.Descriptor.IsRepeated &&
+ //?? just returns true ?? extension.Descriptor.type.isPackable() &&
+ wireType == FieldMappingAttribute.WireTypeFromFieldType(extension.Descriptor.FieldType, true /* isPacked */)) {
+ packed = true; // Packed value.
+ } else {
+ unknown = true; // Wrong wire type.
+ }
+
+ if (unknown) { // Unknown field or wrong wire type. Skip.
+ return input.SkipField(tag);
+ }
+
+ if (packed) {
+ int length = (int)Math.Min(int.MaxValue, input.ReadRawVarint32());
+ int limit = input.PushLimit(length);
+ if (extension.Descriptor.FieldType == FieldType.Enum) {
+ while (!input.ReachedLimit) {
+ int rawValue = input.ReadEnum();
+ Object value =
+ extension.Descriptor.EnumType.FindValueByNumber(rawValue);
+ if (value == null) {
+ // If the number isn't recognized as a valid value for this
+ // enum, drop it (don't even add it to unknownFields).
+ return true;
+ }
+ extensions.AddRepeatedField(extension.Descriptor, value);
+ }
+ } else {
+ while (!input.ReachedLimit) {
+ Object value = input.ReadPrimitiveField(extension.Descriptor.FieldType);
+ extensions.AddRepeatedField(extension.Descriptor, value);
+ }
+ }
+ input.PopLimit(limit);
+ } else {
+ Object value;
+ switch (extension.Descriptor.MappedType) {
+ case MappedType.Message: {
+ IBuilderLite subBuilder = null;
+ if (!extension.Descriptor.IsRepeated) {
+ IMessageLite existingValue = extensions[extension.Descriptor] as IMessageLite;
+ if (existingValue != null) {
+ subBuilder = existingValue.WeakToBuilder();
+ }
+ }
+ if (subBuilder == null) {
+ subBuilder = extension.MessageDefaultInstance.WeakCreateBuilderForType();
+ }
+ if (extension.Descriptor.FieldType == FieldType.Group) {
+ input.ReadGroup(extension.Number, subBuilder, extensionRegistry);
+ } else {
+ input.ReadMessage(subBuilder, extensionRegistry);
+ }
+ value = subBuilder.WeakBuild();
+ break;
+ }
+ case MappedType.Enum:
+ int rawValue = input.ReadEnum();
+ value = extension.Descriptor.EnumType.FindValueByNumber(rawValue);
+ // If the number isn't recognized as a valid value for this enum,
+ // drop it.
+ if (value == null) {
+ return true;
+ }
+ break;
+ default:
+ value = input.ReadPrimitiveField(extension.Descriptor.FieldType);
+ break;
+ }
+
+ if (extension.Descriptor.IsRepeated) {
+ extensions.AddRepeatedField(extension.Descriptor, value);
+ } else {
+ extensions[extension.Descriptor] = value;
+ }
+ }
+
+ return true;
+ }
+
+ #region Reflection
+
+ public object this[IFieldDescriptorLite field, int index] {
+ set {
+ if (field.IsExtension) {
+ ExtendableMessageLite<TMessage, TBuilder> message = MessageBeingBuilt;
+ message.Extensions[field, index] = value;
+ } else {
+ throw new NotSupportedException("Not supported in the lite runtime.");
+ }
+ }
+ }
+
+ public object this[IFieldDescriptorLite field] {
+ set {
+ if (field.IsExtension) {
+ ExtendableMessageLite<TMessage, TBuilder> message = MessageBeingBuilt;
+ message.Extensions[field] = value;
+ } else {
+ throw new NotSupportedException("Not supported in the lite runtime.");
+ }
+ }
+ }
+
+ public TBuilder ClearField(IFieldDescriptorLite field) {
+ if (field.IsExtension) {
+ ExtendableMessageLite<TMessage, TBuilder> message = MessageBeingBuilt;
+ message.Extensions.ClearField(field);
+ return ThisBuilder;
+ } else {
+ throw new NotSupportedException("Not supported in the lite runtime.");
+ }
+ }
+
+ public TBuilder AddRepeatedField(IFieldDescriptorLite field, object value) {
+ if (field.IsExtension) {
+ ExtendableMessageLite<TMessage, TBuilder> message = MessageBeingBuilt;
+ message.Extensions.AddRepeatedField(field, value);
+ return ThisBuilder;
+ } else {
+ throw new NotSupportedException("Not supported in the lite runtime.");
+ }
+ }
+
+ protected void MergeExtensionFields(ExtendableMessageLite<TMessage, TBuilder> other) {
+ MessageBeingBuilt.Extensions.MergeFrom(other.Extensions);
+ }
+ #endregion
+ }
+}
diff --git a/src/ProtocolBuffers/ExtendableMessage.cs b/src/ProtocolBuffers/ExtendableMessage.cs
index 4450f4f9..c67b5a1d 100644
--- a/src/ProtocolBuffers/ExtendableMessage.cs
+++ b/src/ProtocolBuffers/ExtendableMessage.cs
@@ -102,8 +102,8 @@ namespace Google.ProtocolBuffers {
public override IDictionary<FieldDescriptor, object> AllFields {
get {
IDictionary<FieldDescriptor, object> result = GetMutableFieldMap();
- foreach(KeyValuePair<FieldDescriptor, object> entry in extensions.AllFields) {
- result[entry.Key] = entry.Value;
+ foreach(KeyValuePair<IFieldDescriptorLite, object> entry in extensions.AllFields) {
+ result[(FieldDescriptor)entry.Key] = entry.Value;
}
return Dictionaries.AsReadOnly(result);
}
@@ -173,9 +173,9 @@ namespace Google.ProtocolBuffers {
/// TODO(jonskeet): See if we can improve this in terms of readability.
/// </summary>
protected class ExtensionWriter {
- readonly IEnumerator<KeyValuePair<FieldDescriptor, object>> iterator;
+ readonly IEnumerator<KeyValuePair<IFieldDescriptorLite, object>> iterator;
readonly FieldSet extensions;
- KeyValuePair<FieldDescriptor, object>? next = null;
+ KeyValuePair<IFieldDescriptorLite, object>? next = null;
internal ExtensionWriter(ExtendableMessage<TMessage, TBuilder> message) {
extensions = message.extensions;
diff --git a/src/ProtocolBuffers/ExtendableMessageLite.cs b/src/ProtocolBuffers/ExtendableMessageLite.cs
new file mode 100644
index 00000000..aed8545d
--- /dev/null
+++ b/src/ProtocolBuffers/ExtendableMessageLite.cs
@@ -0,0 +1,184 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// 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.
+#endregion
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using Google.ProtocolBuffers.Collections;
+
+namespace Google.ProtocolBuffers {
+ public abstract class ExtendableMessageLite<TMessage, TBuilder> : GeneratedMessageLite<TMessage, TBuilder>
+ where TMessage : GeneratedMessageLite<TMessage, TBuilder>
+ where TBuilder : GeneratedBuilderLite<TMessage, TBuilder> {
+
+ protected ExtendableMessageLite() { }
+ private readonly FieldSet extensions = FieldSet.CreateInstance();
+
+ /// <summary>
+ /// Access for the builder.
+ /// </summary>
+ internal FieldSet Extensions {
+ get { return extensions; }
+ }
+
+ public override bool Equals(object obj) {
+ ExtendableMessageLite<TMessage, TBuilder> other = obj as ExtendableMessageLite<TMessage, TBuilder>;
+ return !ReferenceEquals(null, other) &&
+ Dictionaries.Equals(extensions.AllFields, other.extensions.AllFields);
+ }
+
+ public override int GetHashCode() {
+ return Dictionaries.GetHashCode(extensions.AllFields);
+ }
+
+ /// <summary>
+ /// writes the extensions to the text stream
+ /// </summary>
+ public override void PrintTo(System.IO.TextWriter writer) {
+ foreach (KeyValuePair<IFieldDescriptorLite, object> entry in extensions.AllFields) {
+ string fn = string.Format("[{0}]", entry.Key.FullName);
+ if (entry.Key.IsRepeated) {
+ foreach (object o in ((IEnumerable)entry.Value))
+ PrintField(fn, true, o, writer);
+ } else {
+ PrintField(fn, true, entry.Value, writer);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Checks if a singular extension is present.
+ /// </summary>
+ public bool HasExtension<TExtension>(GeneratedExtensionLite<TMessage, TExtension> extension) {
+ VerifyExtensionContainingType(extension);
+ return extensions.HasField(extension.Descriptor);
+ }
+
+ /// <summary>
+ /// Returns the number of elements in a repeated extension.
+ /// </summary>
+ public int GetExtensionCount<TExtension>(GeneratedExtensionLite<TMessage, IList<TExtension>> extension) {
+ VerifyExtensionContainingType(extension);
+ return extensions.GetRepeatedFieldCount(extension.Descriptor);
+ }
+
+ /// <summary>
+ /// Returns the value of an extension.
+ /// </summary>
+ public TExtension GetExtension<TExtension>(GeneratedExtensionLite<TMessage, TExtension> extension) {
+ VerifyExtensionContainingType(extension);
+ object value = extensions[extension.Descriptor];
+ if (value == null) {
+ return extension.DefaultValue;
+ } else {
+ return (TExtension)extension.FromReflectionType(value);
+ }
+ }
+
+ /// <summary>
+ /// Returns one element of a repeated extension.
+ /// </summary>
+ public TExtension GetExtension<TExtension>(GeneratedExtensionLite<TMessage, IList<TExtension>> extension, int index) {
+ VerifyExtensionContainingType(extension);
+ return (TExtension)extension.SingularFromReflectionType(extensions[extension.Descriptor, index]);
+ }
+
+ /// <summary>
+ /// Called to check if all extensions are initialized.
+ /// </summary>
+ protected bool ExtensionsAreInitialized {
+ get { return extensions.IsInitialized; }
+ }
+
+ public override bool IsInitialized {
+ get {
+ return ExtensionsAreInitialized;
+ }
+ }
+
+ /// <summary>
+ /// Used by subclasses to serialize extensions. Extension ranges may be
+ /// interleaves with field numbers, but we must write them in canonical
+ /// (sorted by field number) order. This class helps us to write individual
+ /// ranges of extensions at once.
+ ///
+ /// TODO(jonskeet): See if we can improve this in terms of readability.
+ /// </summary>
+ protected class ExtensionWriter {
+ readonly IEnumerator<KeyValuePair<IFieldDescriptorLite, object>> iterator;
+ readonly FieldSet extensions;
+ KeyValuePair<IFieldDescriptorLite, object>? next = null;
+
+ internal ExtensionWriter(ExtendableMessageLite<TMessage, TBuilder> message) {
+ extensions = message.extensions;
+ iterator = message.extensions.GetEnumerator();
+ if (iterator.MoveNext()) {
+ next = iterator.Current;
+ }
+ }
+
+ public void WriteUntil(int end, CodedOutputStream output) {
+ while (next != null && next.Value.Key.FieldNumber < end) {
+ extensions.WriteField(next.Value.Key, next.Value.Value, output);
+ if (iterator.MoveNext()) {
+ next = iterator.Current;
+ } else {
+ next = null;
+ }
+ }
+ }
+ }
+
+ protected ExtensionWriter CreateExtensionWriter(ExtendableMessageLite<TMessage, TBuilder> message) {
+ return new ExtensionWriter(message);
+ }
+
+ /// <summary>
+ /// Called by subclasses to compute the size of extensions.
+ /// </summary>
+ protected int ExtensionsSerializedSize {
+ get { return extensions.SerializedSize; }
+ }
+
+ internal void VerifyExtensionContainingType<TExtension>(GeneratedExtensionLite<TMessage, TExtension> extension) {
+ if (!ReferenceEquals(extension.ContainingTypeDefaultInstance, DefaultInstanceForType)) {
+ // This can only happen if someone uses unchecked operations.
+ throw new ArgumentException(
+ String.Format("Extension is for type \"{0}\" which does not match message type \"{1}\".",
+ extension.ContainingTypeDefaultInstance, DefaultInstanceForType
+ ));
+ }
+ }
+ }
+}
diff --git a/src/ProtocolBuffers/ExtensionInfo.cs b/src/ProtocolBuffers/ExtensionInfo.cs
index 4c877ab8..5d99b8ff 100644
--- a/src/ProtocolBuffers/ExtensionInfo.cs
+++ b/src/ProtocolBuffers/ExtensionInfo.cs
@@ -36,24 +36,42 @@ using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers
{
- public sealed class ExtensionInfo {
+ public sealed class ExtensionInfo : IGeneratedExtensionLite {
/// <summary>
/// The extension's descriptor
/// </summary>
public FieldDescriptor Descriptor { get; private set; }
- /// <summary>
+ IFieldDescriptorLite IGeneratedExtensionLite.Descriptor { get { return Descriptor; } }
+
+ /// <summary>
/// A default instance of the extensions's type, if it has a message type,
/// or null otherwise.
/// </summary>
- public IMessage DefaultInstance { get; private set; }
+ public IMessageLite DefaultInstance { get; private set; }
internal ExtensionInfo(FieldDescriptor descriptor) : this(descriptor, null) {
}
- internal ExtensionInfo(FieldDescriptor descriptor, IMessage defaultInstance) {
+ internal ExtensionInfo(FieldDescriptor descriptor, IMessageLite defaultInstance) {
Descriptor = descriptor;
DefaultInstance = defaultInstance;
}
+
+ #region IGeneratedExtensionLite Members
+
+ int IGeneratedExtensionLite.Number {
+ get { return Descriptor.FieldNumber; }
+ }
+
+ object IGeneratedExtensionLite.ContainingType {
+ get { return Descriptor; }
+ }
+
+ IMessageLite IGeneratedExtensionLite.MessageDefaultInstance {
+ get { return DefaultInstance; }
+ }
+
+ #endregion
}
} \ No newline at end of file
diff --git a/src/ProtocolBuffers/ExtensionRegistry.cs b/src/ProtocolBuffers/ExtensionRegistry.cs
index 154b6902..b7690731 100644
--- a/src/ProtocolBuffers/ExtensionRegistry.cs
+++ b/src/ProtocolBuffers/ExtensionRegistry.cs
@@ -88,23 +88,20 @@ namespace Google.ProtocolBuffers {
/// could take advantage of this to inject a mutable object into a message
/// belonging to privileged code and create mischief.</para>
/// </remarks>
- public sealed class ExtensionRegistry {
-
+ public sealed partial class ExtensionRegistry {
+#if !LITE
private static readonly ExtensionRegistry empty = new ExtensionRegistry(
new Dictionary<string, ExtensionInfo>(),
- new Dictionary<DescriptorIntPair, ExtensionInfo>(),
+ new Dictionary<ExtensionIntPair, IGeneratedExtensionLite>(),
true);
private readonly IDictionary<string, ExtensionInfo> extensionsByName;
- private readonly IDictionary<DescriptorIntPair, ExtensionInfo> extensionsByNumber;
- private readonly bool readOnly;
private ExtensionRegistry(IDictionary<String, ExtensionInfo> extensionsByName,
- IDictionary<DescriptorIntPair, ExtensionInfo> extensionsByNumber,
- bool readOnly) {
+ IDictionary<ExtensionIntPair, IGeneratedExtensionLite> extensionsByNumber,
+ bool readOnly)
+ : this(extensionsByNumber, readOnly) {
this.extensionsByName = extensionsByName;
- this.extensionsByNumber = extensionsByNumber;
- this.readOnly = readOnly;
}
/// <summary>
@@ -112,19 +109,13 @@ namespace Google.ProtocolBuffers {
/// </summary>
public static ExtensionRegistry CreateInstance() {
return new ExtensionRegistry(new Dictionary<string, ExtensionInfo>(),
- new Dictionary<DescriptorIntPair, ExtensionInfo>(), false);
- }
-
- /// <summary>
- /// Get the unmodifiable singleton empty instance.
- /// </summary>
- public static ExtensionRegistry Empty {
- get { return empty; }
+ new Dictionary<ExtensionIntPair, IGeneratedExtensionLite>(), false);
}
public ExtensionRegistry AsReadOnly() {
return new ExtensionRegistry(extensionsByName, extensionsByNumber, true);
}
+#endif
/// <summary>
/// Finds an extension by fully-qualified field name, in the
@@ -146,9 +137,9 @@ namespace Google.ProtocolBuffers {
/// </summary>
public ExtensionInfo this[MessageDescriptor containingType, int fieldNumber] {
get {
- ExtensionInfo ret;
- extensionsByNumber.TryGetValue(new DescriptorIntPair(containingType, fieldNumber), out ret);
- return ret;
+ IGeneratedExtensionLite ret;
+ extensionsByNumber.TryGetValue(new ExtensionIntPair(containingType, fieldNumber), out ret);
+ return ret as ExtensionInfo;
}
}
@@ -198,7 +189,7 @@ namespace Google.ProtocolBuffers {
}
extensionsByName[extension.Descriptor.FullName] = extension;
- extensionsByNumber[new DescriptorIntPair(extension.Descriptor.ContainingType,
+ extensionsByNumber[new ExtensionIntPair(extension.Descriptor.ContainingType,
extension.Descriptor.FieldNumber)] = extension;
FieldDescriptor field = extension.Descriptor;
@@ -212,34 +203,5 @@ namespace Google.ProtocolBuffers {
extensionsByName[field.MessageType.FullName] = extension;
}
}
-
- /// <summary>
- /// Nested type just used to represent a pair of MessageDescriptor and int, as
- /// the key into the "by number" map.
- /// </summary>
- private struct DescriptorIntPair : IEquatable<DescriptorIntPair> {
- readonly MessageDescriptor descriptor;
- readonly int number;
-
- internal DescriptorIntPair(MessageDescriptor descriptor, int number) {
- this.descriptor = descriptor;
- this.number = number;
- }
-
- public override int GetHashCode() {
- return descriptor.GetHashCode() * ((1 << 16) - 1) + number;
- }
-
- public override bool Equals(object obj) {
- if (!(obj is DescriptorIntPair)) {
- return false;
- }
- return Equals((DescriptorIntPair)obj);
- }
-
- public bool Equals(DescriptorIntPair other) {
- return descriptor == other.descriptor && number == other.number;
- }
- }
}
}
diff --git a/src/ProtocolBuffers/ExtensionRegistryLite.cs b/src/ProtocolBuffers/ExtensionRegistryLite.cs
new file mode 100644
index 00000000..8e420a81
--- /dev/null
+++ b/src/ProtocolBuffers/ExtensionRegistryLite.cs
@@ -0,0 +1,179 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// 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.
+#endregion
+
+using System.Collections.Generic;
+using System;
+
+namespace Google.ProtocolBuffers {
+
+ /// <summary>
+ /// A table of known extensions, searchable by name or field number. When
+ /// parsing a protocol message that might have extensions, you must provide
+ /// an <see cref="ExtensionRegistry"/> in which you have registered any extensions
+ /// that you want to be able to parse. Otherwise, those extensions will just
+ /// be treated like unknown fields.
+ /// </summary>
+ /// <example>
+ /// For example, if you had the <c>.proto</c> file:
+ /// <code>
+ /// option java_class = "MyProto";
+ ///
+ /// message Foo {
+ /// extensions 1000 to max;
+ /// }
+ ///
+ /// extend Foo {
+ /// optional int32 bar;
+ /// }
+ /// </code>
+ ///
+ /// Then you might write code like:
+ ///
+ /// <code>
+ /// extensionRegistry registry = extensionRegistry.CreateInstance();
+ /// registry.Add(MyProto.Bar);
+ /// MyProto.Foo message = MyProto.Foo.ParseFrom(input, registry);
+ /// </code>
+ /// </example>
+ ///
+ /// <remarks>
+ /// <para>You might wonder why this is necessary. Two alternatives might come to
+ /// mind. First, you might imagine a system where generated extensions are
+ /// automatically registered when their containing classes are loaded. This
+ /// is a popular technique, but is bad design; among other things, it creates a
+ /// situation where behavior can change depending on what classes happen to be
+ /// loaded. It also introduces a security vulnerability, because an
+ /// unprivileged class could cause its code to be called unexpectedly from a
+ /// privileged class by registering itself as an extension of the right type.
+ /// </para>
+ /// <para>Another option you might consider is lazy parsing: do not parse an
+ /// extension until it is first requested, at which point the caller must
+ /// provide a type to use. This introduces a different set of problems. First,
+ /// it would require a mutex lock any time an extension was accessed, which
+ /// would be slow. Second, corrupt data would not be detected until first
+ /// access, at which point it would be much harder to deal with it. Third, it
+ /// could violate the expectation that message objects are immutable, since the
+ /// type provided could be any arbitrary message class. An unprivileged user
+ /// could take advantage of this to inject a mutable object into a message
+ /// belonging to privileged code and create mischief.</para>
+ /// </remarks>
+ public sealed partial class ExtensionRegistry {
+ private readonly IDictionary<ExtensionIntPair, IGeneratedExtensionLite> extensionsByNumber;
+ private readonly bool readOnly;
+
+ private ExtensionRegistry(IDictionary<ExtensionIntPair, IGeneratedExtensionLite> extensionsByNumber,
+ bool readOnly) {
+ this.extensionsByNumber = extensionsByNumber;
+ this.readOnly = readOnly;
+ }
+
+#if LITE
+ private static readonly ExtensionRegistry empty = new ExtensionRegistry(
+ new Dictionary<ExtensionIntPair, IGeneratedExtensionLite>(),
+ true);
+
+ /// <summary>
+ /// Construct a new, empty instance.
+ /// </summary>
+ public static ExtensionRegistry CreateInstance() {
+ return new ExtensionRegistry(
+ new Dictionary<ExtensionIntPair, IGeneratedExtensionLite>(), false);
+ }
+ public ExtensionRegistry AsReadOnly() {
+ return new ExtensionRegistry(extensionsByNumber, true);
+ }
+
+#endif
+
+ /// <summary>
+ /// Get the unmodifiable singleton empty instance.
+ /// </summary>
+ public static ExtensionRegistry Empty {
+ get { return empty; }
+ }
+
+ /// <summary>
+ /// Finds an extension by containing type and field number.
+ /// A null reference is returned if the extension can't be found.
+ /// </summary>
+ public IGeneratedExtensionLite this[IMessageLite containingType, int fieldNumber] {
+ get {
+ IGeneratedExtensionLite ret;
+ extensionsByNumber.TryGetValue(new ExtensionIntPair(containingType, fieldNumber), out ret);
+ return ret;
+ }
+ }
+
+ /// <summary>
+ /// Add an extension from a generated file to the registry.
+ /// </summary>
+ public void Add(IGeneratedExtensionLite extension) {
+ if (readOnly) {
+ throw new InvalidOperationException("Cannot add entries to a read-only extension registry");
+ }
+ extensionsByNumber.Add(
+ new ExtensionIntPair(extension.ContainingType, extension.Number),
+ extension);
+ }
+
+ /// <summary>
+ /// Nested type just used to represent a pair of MessageDescriptor and int, as
+ /// the key into the "by number" map.
+ /// </summary>
+ private struct ExtensionIntPair : IEquatable<ExtensionIntPair> {
+ readonly object msgType;
+ readonly int number;
+
+ internal ExtensionIntPair(object msgType, int number) {
+ this.msgType = msgType;
+ this.number = number;
+ }
+
+ public override int GetHashCode() {
+ return msgType.GetHashCode() * ((1 << 16) - 1) + number;
+ }
+
+ public override bool Equals(object obj) {
+ if (!(obj is ExtensionIntPair)) {
+ return false;
+ }
+ return Equals((ExtensionIntPair)obj);
+ }
+
+ public bool Equals(ExtensionIntPair other) {
+ return msgType.Equals(other.msgType) && number == other.number;
+ }
+ }
+ }
+}
diff --git a/src/ProtocolBuffers/FieldAccess/RepeatedMessageAccessor.cs b/src/ProtocolBuffers/FieldAccess/RepeatedMessageAccessor.cs
index 893b0285..df6680cb 100644
--- a/src/ProtocolBuffers/FieldAccess/RepeatedMessageAccessor.cs
+++ b/src/ProtocolBuffers/FieldAccess/RepeatedMessageAccessor.cs
@@ -71,7 +71,7 @@ namespace Google.ProtocolBuffers.FieldAccess {
}
// No... so let's create a builder of the right type, and merge the value in.
- IMessage message = (IMessage) value;
+ IMessageLite message = (IMessageLite) value;
return CreateBuilder().WeakMergeFrom(message).WeakBuild();
}
diff --git a/src/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs b/src/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs
index ea422c94..838bc5a2 100644
--- a/src/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs
+++ b/src/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs
@@ -67,7 +67,7 @@ namespace Google.ProtocolBuffers.FieldAccess {
}
// No... so let's create a builder of the right type, and merge the value in.
- IMessage message = (IMessage) value;
+ IMessageLite message = (IMessageLite) value;
return CreateBuilder().WeakMergeFrom(message).WeakBuild();
}
diff --git a/src/ProtocolBuffers/FieldSet.cs b/src/ProtocolBuffers/FieldSet.cs
index 7c373b95..c3e3d740 100644
--- a/src/ProtocolBuffers/FieldSet.cs
+++ b/src/ProtocolBuffers/FieldSet.cs
@@ -39,6 +39,21 @@ using Google.ProtocolBuffers.Collections;
using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers {
+
+ public interface IFieldDescriptorLite : IComparable<IFieldDescriptorLite> {
+ bool IsRepeated { get; }
+ bool IsRequired { get; }
+ bool IsPacked { get; }
+ bool IsExtension { get; }
+ bool MessageSetWireFormat { get; } //field.ContainingType.Options.MessageSetWireFormat
+ int FieldNumber { get; }
+ string FullName { get; }
+ IEnumLiteMap EnumType { get; }
+ FieldType FieldType { get; }
+ MappedType MappedType { get; }
+ object DefaultValue { get; }
+ }
+
/// <summary>
/// A class which represents an arbitrary set of fields of some message type.
/// This is used to implement DynamicMessage, and also to represent extensions
@@ -56,17 +71,17 @@ namespace Google.ProtocolBuffers {
/// </summary>
internal sealed class FieldSet {
- private static readonly FieldSet defaultInstance = new FieldSet(new Dictionary<FieldDescriptor, object>()).MakeImmutable();
+ private static readonly FieldSet defaultInstance = new FieldSet(new Dictionary<IFieldDescriptorLite, object>()).MakeImmutable();
- private IDictionary<FieldDescriptor, object> fields;
+ private IDictionary<IFieldDescriptorLite, object> fields;
- private FieldSet(IDictionary<FieldDescriptor, object> fields) {
+ private FieldSet(IDictionary<IFieldDescriptorLite, object> fields) {
this.fields = fields;
}
public static FieldSet CreateInstance() {
// Use SortedList to keep fields in the canonical order
- return new FieldSet(new SortedList<FieldDescriptor, object>());
+ return new FieldSet(new SortedList<IFieldDescriptorLite, object>());
}
/// <summary>
@@ -85,8 +100,8 @@ namespace Google.ProtocolBuffers {
}
if (hasRepeats) {
- var tmp = new SortedList<FieldDescriptor, object>();
- foreach (KeyValuePair<FieldDescriptor, object> entry in fields) {
+ var tmp = new SortedList<IFieldDescriptorLite, object>();
+ foreach (KeyValuePair<IFieldDescriptorLite, object> entry in fields) {
IList<object> list = entry.Value as IList<object>;
tmp[entry.Key] = list == null ? entry.Value : Lists.AsReadOnly(list);
}
@@ -110,14 +125,26 @@ namespace Google.ProtocolBuffers {
/// is immutable, the entries may not be (i.e. any repeated values are represented by
/// mutable lists). The behaviour is not specified if the contents are mutated.
/// </summary>
- internal IDictionary<FieldDescriptor, object> AllFields {
+ internal IDictionary<IFieldDescriptorLite, object> AllFields {
get { return Dictionaries.AsReadOnly(fields); }
}
-
+#if !LITE
+ /// <summary>
+ /// Force coercion to full descriptor dictionary.
+ /// </summary>
+ internal IDictionary<Descriptors.FieldDescriptor, object> AllFieldDescriptors {
+ get {
+ SortedList<Descriptors.FieldDescriptor, object> copy = new SortedList<Google.ProtocolBuffers.Descriptors.FieldDescriptor, object>();
+ foreach (KeyValuePair<IFieldDescriptorLite, object> fd in fields)
+ copy.Add((Descriptors.FieldDescriptor)fd.Key, fd.Value);
+ return Dictionaries.AsReadOnly(copy);
+ }
+ }
+#endif
/// <summary>
- /// See <see cref="IMessage.HasField"/>.
+ /// See <see cref="IMessageLite.HasField"/>.
/// </summary>
- public bool HasField(FieldDescriptor field) {
+ public bool HasField(IFieldDescriptorLite field) {
if (field.IsRepeated) {
throw new ArgumentException("HasField() can only be called on non-repeated fields.");
}
@@ -133,7 +160,7 @@ namespace Google.ProtocolBuffers {
}
/// <summary>
- /// See <see cref="IMessage.Item(FieldDescriptor)"/>
+ /// See <see cref="IMessageLite.Item(IFieldDescriptorLite)"/>
/// </summary>
/// <remarks>
/// If the field is not set, the behaviour when fetching this property varies by field type:
@@ -153,7 +180,7 @@ namespace Google.ProtocolBuffers {
/// to ensure it is of an appropriate type.
/// </remarks>
///
- internal object this[FieldDescriptor field] {
+ internal object this[IFieldDescriptorLite field] {
get {
object result;
if (fields.TryGetValue(field, out result)) {
@@ -191,9 +218,9 @@ namespace Google.ProtocolBuffers {
}
/// <summary>
- /// See <see cref="IMessage.Item(FieldDescriptor,int)" />
+ /// See <see cref="IMessageLite.Item(IFieldDescriptorLite,int)" />
/// </summary>
- internal object this[FieldDescriptor field, int index] {
+ internal object this[IFieldDescriptorLite field, int index] {
get {
if (!field.IsRepeated) {
throw new ArgumentException("Indexer specifying field and index can only be called on repeated fields.");
@@ -217,7 +244,7 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// See <see cref="IBuilder{TMessage, TBuilder}.AddRepeatedField" />
/// </summary>
- internal void AddRepeatedField(FieldDescriptor field, object value) {
+ internal void AddRepeatedField(IFieldDescriptorLite field, object value) {
if (!field.IsRepeated) {
throw new ArgumentException("AddRepeatedField can only be called on repeated fields.");
}
@@ -233,12 +260,12 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// Returns an enumerator for the field map. Used to write the fields out.
/// </summary>
- internal IEnumerator<KeyValuePair<FieldDescriptor, object>> GetEnumerator() {
+ internal IEnumerator<KeyValuePair<IFieldDescriptorLite, object>> GetEnumerator() {
return fields.GetEnumerator();
}
/// <summary>
- /// See <see cref="IMessage.IsInitialized" />
+ /// See <see cref="IMessageLite.IsInitialized" />
/// </summary>
/// <remarks>
/// Since FieldSet itself does not have any way of knowing about
@@ -248,17 +275,17 @@ namespace Google.ProtocolBuffers {
/// </remarks>
internal bool IsInitialized {
get {
- foreach (KeyValuePair<FieldDescriptor, object> entry in fields) {
- FieldDescriptor field = entry.Key;
+ foreach (KeyValuePair<IFieldDescriptorLite, object> entry in fields) {
+ IFieldDescriptorLite field = entry.Key;
if (field.MappedType == MappedType.Message) {
if (field.IsRepeated) {
- foreach(IMessage message in (IEnumerable) entry.Value) {
+ foreach(IMessageLite message in (IEnumerable) entry.Value) {
if (!message.IsInitialized) {
return false;
}
}
} else {
- if (!((IMessage) entry.Value).IsInitialized) {
+ if (!((IMessageLite)entry.Value).IsInitialized) {
return false;
}
}
@@ -273,8 +300,8 @@ namespace Google.ProtocolBuffers {
/// descriptor are present in this field set, as well as whether
/// all the embedded messages are themselves initialized.
/// </summary>
- internal bool IsInitializedWithRespectTo(MessageDescriptor type) {
- foreach (FieldDescriptor field in type.Fields) {
+ internal bool IsInitializedWithRespectTo(IEnumerable typeFields) {
+ foreach (IFieldDescriptorLite field in typeFields) {
if (field.IsRequired && !HasField(field)) {
return false;
}
@@ -285,14 +312,14 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// See <see cref="IBuilder{TMessage, TBuilder}.ClearField" />
/// </summary>
- public void ClearField(FieldDescriptor field) {
+ public void ClearField(IFieldDescriptorLite field) {
fields.Remove(field);
}
/// <summary>
- /// See <see cref="IMessage.GetRepeatedFieldCount" />
+ /// See <see cref="IMessageLite.GetRepeatedFieldCount" />
/// </summary>
- public int GetRepeatedFieldCount(FieldDescriptor field) {
+ public int GetRepeatedFieldCount(IFieldDescriptorLite field) {
if (!field.IsRepeated) {
throw new ArgumentException("GetRepeatedFieldCount() can only be called on repeated fields.");
}
@@ -300,64 +327,63 @@ namespace Google.ProtocolBuffers {
return ((IList<object>) this[field]).Count;
}
+#if !LITE
+ /// <summary>
+ /// See <see cref="IBuilder{TMessage, TBuilder}.MergeFrom(IMessageLite)" />
+ /// </summary>
+ public void MergeFrom(IMessage other) {
+ foreach (KeyValuePair<Descriptors.FieldDescriptor, object> fd in other.AllFields)
+ MergeField(fd.Key, fd.Value);
+ }
+#endif
+
/// <summary>
/// Implementation of both <c>MergeFrom</c> methods.
/// </summary>
/// <param name="otherFields"></param>
- private void MergeFields(IEnumerable<KeyValuePair<FieldDescriptor, object>> otherFields) {
+ public void MergeFrom(FieldSet other) {
// Note: We don't attempt to verify that other's fields have valid
// types. Doing so would be a losing battle. We'd have to verify
// all sub-messages as well, and we'd have to make copies of all of
// them to insure that they don't change after verification (since
- // the IMessage interface itself cannot enforce immutability of
+ // the IMessageLite interface itself cannot enforce immutability of
// implementations).
// TODO(jonskeet): Provide a function somewhere called MakeDeepCopy()
// which allows people to make secure deep copies of messages.
- foreach (KeyValuePair<FieldDescriptor, object> entry in otherFields) {
- FieldDescriptor field = entry.Key;
- object existingValue;
- fields.TryGetValue(field, out existingValue);
- if (field.IsRepeated) {
- if (existingValue == null) {
- existingValue = new List<object>();
- fields[field] = existingValue;
- }
- IList<object> list = (IList<object>) existingValue;
- foreach (object otherValue in (IEnumerable) entry.Value) {
- list.Add(otherValue);
- }
- } else if (field.MappedType == MappedType.Message && existingValue != null) {
- IMessage existingMessage = (IMessage)existingValue;
- IMessage merged = existingMessage.WeakToBuilder()
- .WeakMergeFrom((IMessage) entry.Value)
- .WeakBuild();
- this[field] = merged;
- } else {
- this[field] = entry.Value;
- }
+ foreach (KeyValuePair<IFieldDescriptorLite, object> entry in other.fields) {
+ MergeField(entry.Key, entry.Value);
}
}
- /// <summary>
- /// See <see cref="IBuilder{TMessage, TBuilder}.MergeFrom(IMessage)" />
- /// </summary>
- public void MergeFrom(IMessage other) {
- MergeFields(other.AllFields);
- }
-
- /// <summary>
- /// Like <see cref="MergeFrom(IMessage)"/>, but merges from another <c>FieldSet</c>.
- /// </summary>
- public void MergeFrom(FieldSet other) {
- MergeFields(other.fields);
+ private void MergeField(IFieldDescriptorLite field, object mergeValue) {
+ object existingValue;
+ fields.TryGetValue(field, out existingValue);
+ if (field.IsRepeated) {
+ if (existingValue == null) {
+ existingValue = new List<object>();
+ fields[field] = existingValue;
+ }
+ IList<object> list = (IList<object>) existingValue;
+ foreach (object otherValue in (IEnumerable)mergeValue) {
+ list.Add(otherValue);
+ }
+ } else if (field.MappedType == MappedType.Message && existingValue != null) {
+ IMessageLite existingMessage = (IMessageLite)existingValue;
+ IMessageLite merged = existingMessage.WeakToBuilder()
+ .WeakMergeFrom((IMessageLite)mergeValue)
+ .WeakBuild();
+ this[field] = merged;
+ } else {
+ this[field] = mergeValue;
+ }
}
/// <summary>
- /// See <see cref="IMessage.WriteTo(CodedOutputStream)" />.
+ /// See <see cref="IMessageLite.WriteTo(CodedOutputStream)" />.
/// </summary>
public void WriteTo(CodedOutputStream output) {
- foreach (KeyValuePair<FieldDescriptor, object> entry in fields) {
+ foreach (KeyValuePair<IFieldDescriptorLite, object> entry in fields) {
WriteField(entry.Key, entry.Value, output);
}
}
@@ -365,9 +391,9 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// Writes a single field to a CodedOutputStream.
/// </summary>
- public void WriteField(FieldDescriptor field, Object value, CodedOutputStream output) {
- if (field.IsExtension && field.ContainingType.Options.MessageSetWireFormat) {
- output.WriteMessageSetExtension(field.FieldNumber, (IMessage) value);
+ public void WriteField(IFieldDescriptorLite field, Object value, CodedOutputStream output) {
+ if (field.IsExtension && field.MessageSetWireFormat) {
+ output.WriteMessageSetExtension(field.FieldNumber, (IMessageLite) value);
} else {
if (field.IsRepeated) {
IEnumerable valueList = (IEnumerable) value;
@@ -395,18 +421,18 @@ namespace Google.ProtocolBuffers {
}
/// <summary>
- /// See <see cref="IMessage.SerializedSize" />. It's up to the caller to
+ /// See <see cref="IMessageLite.SerializedSize" />. It's up to the caller to
/// cache the resulting size if desired.
/// </summary>
public int SerializedSize {
get {
int size = 0;
- foreach (KeyValuePair<FieldDescriptor, object> entry in fields) {
- FieldDescriptor field = entry.Key;
+ foreach (KeyValuePair<IFieldDescriptorLite, object> entry in fields) {
+ IFieldDescriptorLite field = entry.Key;
object value = entry.Value;
- if (field.IsExtension && field.ContainingType.Options.MessageSetWireFormat) {
- size += CodedOutputStream.ComputeMessageSetExtensionSize(field.FieldNumber, (IMessage)value);
+ if (field.IsExtension && field.MessageSetWireFormat) {
+ size += CodedOutputStream.ComputeMessageSetExtensionSize(field.FieldNumber, (IMessageLite)value);
} else {
if (field.IsRepeated) {
IEnumerable valueList = (IEnumerable)value;
@@ -440,7 +466,7 @@ namespace Google.ProtocolBuffers {
/// </remarks>
/// <exception cref="ArgumentException">The value is not of the right type.</exception>
/// <exception cref="ArgumentNullException">The value is null.</exception>
- private static void VerifyType(FieldDescriptor field, object value) {
+ private static void VerifyType(IFieldDescriptorLite field, object value) {
ThrowHelper.ThrowIfNull(value, "value");
bool isValid = false;
switch (field.MappedType) {
@@ -454,12 +480,17 @@ namespace Google.ProtocolBuffers {
case MappedType.String: isValid = value is string; break;
case MappedType.ByteString: isValid = value is ByteString; break;
case MappedType.Enum:
- EnumValueDescriptor enumValue = value as EnumValueDescriptor;
- isValid = enumValue != null && enumValue.EnumDescriptor == field.EnumType;
+ IEnumLite enumValue = value as IEnumLite;
+ isValid = enumValue != null && field.EnumType.IsValidValue(enumValue);
break;
case MappedType.Message:
- IMessage messageValue = value as IMessage;
- isValid = messageValue != null && messageValue.DescriptorForType == field.MessageType;
+ IMessageLite messageValue = value as IMessageLite;
+ isValid = messageValue != null;
+#if !LITE
+ if (isValid && messageValue is IMessage && field is FieldDescriptor) {
+ isValid = ((IMessage) messageValue).DescriptorForType == ((FieldDescriptor) field).MessageType;
+ }
+#endif
break;
}
@@ -468,10 +499,16 @@ namespace Google.ProtocolBuffers {
// the stack trace which exact call failed, since the whole chain is
// considered one line of code. So, let's make sure to include the
// field name and other useful info in the exception.
- throw new ArgumentException("Wrong object type used with protocol message reflection. "
- + "Message type \"" + field.ContainingType.FullName
- + "\", field \"" + (field.IsExtension ? field.FullName : field.Name)
- + "\", value was type \"" + value.GetType().Name + "\".");
+ string message = "Wrong object type used with protocol message reflection.";
+#if !LITE
+ Google.ProtocolBuffers.Descriptors.FieldDescriptor fieldinfo = field as Google.ProtocolBuffers.Descriptors.FieldDescriptor;
+ if (fieldinfo != null) {
+ message += "Message type \"" + fieldinfo.ContainingType.FullName;
+ message += "\", field \"" + (fieldinfo.IsExtension ? fieldinfo.FullName : fieldinfo.Name);
+ message += "\", value was type \"" + value.GetType().Name + "\".";
+ }
+#endif
+ throw new ArgumentException(message);
}
}
}
diff --git a/src/ProtocolBuffers/GeneratedBuilder.cs b/src/ProtocolBuffers/GeneratedBuilder.cs
index 1124fc86..2ec2762f 100644
--- a/src/ProtocolBuffers/GeneratedBuilder.cs
+++ b/src/ProtocolBuffers/GeneratedBuilder.cs
@@ -148,16 +148,20 @@ namespace Google.ProtocolBuffers {
}
} else if (field.MappedType == MappedType.Message && HasField(field)) {
// Merge singular embedded messages
- IMessage oldValue = (IMessage)this[field];
+ IMessageLite oldValue = (IMessageLite)this[field];
this[field] = oldValue.WeakCreateBuilderForType()
.WeakMergeFrom(oldValue)
- .WeakMergeFrom((IMessage)entry.Value)
+ .WeakMergeFrom((IMessageLite)entry.Value)
.WeakBuildPartial();
} else {
// Just overwrite
this[field] = entry.Value;
}
}
+
+ //Fix for unknown fields not merging, see java's AbstractMessage.Builder<T> line 236
+ MergeUnknownFields(other.UnknownFields);
+
return ThisBuilder;
}
diff --git a/src/ProtocolBuffers/GeneratedBuilderLite.cs b/src/ProtocolBuffers/GeneratedBuilderLite.cs
new file mode 100644
index 00000000..d721fddd
--- /dev/null
+++ b/src/ProtocolBuffers/GeneratedBuilderLite.cs
@@ -0,0 +1,117 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// 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.
+#endregion
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace Google.ProtocolBuffers {
+ /// <summary>
+ /// All generated protocol message builder classes extend this class. It implements
+ /// most of the IBuilder interface using reflection. Users can ignore this class
+ /// as an implementation detail.
+ /// </summary>
+ public abstract class GeneratedBuilderLite<TMessage, TBuilder> : AbstractBuilderLite<TMessage, TBuilder>
+ where TMessage : GeneratedMessageLite<TMessage, TBuilder>
+ where TBuilder : GeneratedBuilderLite<TMessage, TBuilder> {
+
+ /// <summary>
+ /// Returns the message being built at the moment.
+ /// </summary>
+ protected abstract TMessage MessageBeingBuilt { get; }
+
+ public override TBuilder MergeFrom(IMessageLite other) {
+ //do nothing, Lite runtime does not support cross-message merges
+ return ThisBuilder;
+ }
+
+ public abstract TBuilder MergeFrom(TMessage other);
+
+ public override bool IsInitialized {
+ get { return MessageBeingBuilt.IsInitialized; }
+ }
+
+ /// <summary>
+ /// Adds all of the specified values to the given collection.
+ /// </summary>
+ /// <exception cref="ArgumentNullException">Any element of the list is null</exception>
+ protected void AddRange<T>(IEnumerable<T> source, IList<T> destination) {
+ ThrowHelper.ThrowIfNull(source);
+ // We only need to check this for nullable types.
+ if (default(T) == null) {
+ ThrowHelper.ThrowIfAnyNull(source);
+ }
+ List<T> list = destination as List<T>;
+ if (list != null) {
+ list.AddRange(source);
+ } else {
+ foreach (T element in source) {
+ destination.Add(element);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Called by derived classes to parse an unknown field.
+ /// </summary>
+ /// <returns>true unless the tag is an end-group tag</returns>
+ [CLSCompliant(false)]
+ protected virtual bool ParseUnknownField(CodedInputStream input,
+ ExtensionRegistry extensionRegistry, uint tag) {
+ return input.SkipField(tag);
+ }
+
+ /// <summary>
+ /// Like Build(), but will wrap UninitializedMessageException in
+ /// InvalidProtocolBufferException.
+ /// </summary>
+ public TMessage BuildParsed() {
+ if (!IsInitialized) {
+ throw new UninitializedMessageException(MessageBeingBuilt).AsInvalidProtocolBufferException();
+ }
+ return BuildPartial();
+ }
+
+ /// <summary>
+ /// Implementation of <see cref="IBuilder{TMessage, TBuilder}.Build" />.
+ /// </summary>
+ public override TMessage Build() {
+ // If the message is null, we'll throw a more appropriate exception in BuildPartial.
+ if (MessageBeingBuilt != null && !IsInitialized) {
+ throw new UninitializedMessageException(MessageBeingBuilt);
+ }
+ return BuildPartial();
+ }
+ }
+}
diff --git a/src/ProtocolBuffers/GeneratedExtensionBase.cs b/src/ProtocolBuffers/GeneratedExtensionBase.cs
index 813f69cf..aacc0655 100644
--- a/src/ProtocolBuffers/GeneratedExtensionBase.cs
+++ b/src/ProtocolBuffers/GeneratedExtensionBase.cs
@@ -39,6 +39,7 @@ using System.Reflection;
using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers {
+
/// <summary>
/// Base type for all generated extensions.
/// </summary>
@@ -65,7 +66,7 @@ namespace Google.ProtocolBuffers {
public abstract class GeneratedExtensionBase<TExtension> {
private readonly FieldDescriptor descriptor;
- private readonly IMessage messageDefaultInstance;
+ private readonly IMessageLite messageDefaultInstance;
protected GeneratedExtensionBase(FieldDescriptor descriptor, Type singularExtensionType) {
if (!descriptor.IsExtension) {
@@ -79,7 +80,8 @@ namespace Google.ProtocolBuffers {
if (defaultInstanceProperty == null) {
throw new ArgumentException("No public static DefaultInstance property for type " + typeof(TExtension).Name);
}
- messageDefaultInstance = (IMessage)defaultInstanceProperty.GetValue(null, null);
+
+ messageDefaultInstance = (IMessageLite)defaultInstanceProperty.GetValue(null, null);
}
}
@@ -87,10 +89,14 @@ namespace Google.ProtocolBuffers {
get { return descriptor; }
}
+ public int Number {
+ get { return Descriptor.FieldNumber; }
+ }
+
/// <summary>
/// Returns the default message instance for extensions which are message types.
/// </summary>
- public IMessage MessageDefaultInstance {
+ public IMessageLite MessageDefaultInstance {
get { return messageDefaultInstance; }
}
@@ -107,7 +113,7 @@ namespace Google.ProtocolBuffers {
// This should not happen in normal use. But, to be nice, we'll
// copy the message to whatever type the caller was expecting.
return MessageDefaultInstance.WeakCreateBuilderForType()
- .WeakMergeFrom((IMessage)value).WeakBuild();
+ .WeakMergeFrom((IMessageLite)value).WeakBuild();
}
case MappedType.Enum:
// Just return a boxed int - that can be unboxed to the enum
diff --git a/src/ProtocolBuffers/GeneratedExtensionLite.cs b/src/ProtocolBuffers/GeneratedExtensionLite.cs
new file mode 100644
index 00000000..33969f4b
--- /dev/null
+++ b/src/ProtocolBuffers/GeneratedExtensionLite.cs
@@ -0,0 +1,294 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// 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.
+#endregion
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using Google.ProtocolBuffers.Collections;
+using Google.ProtocolBuffers.Descriptors;
+
+namespace Google.ProtocolBuffers {
+
+ public interface IGeneratedExtensionLite {
+ int Number { get; }
+ object ContainingType { get; }
+ IMessageLite MessageDefaultInstance { get; }
+ IFieldDescriptorLite Descriptor { get; }
+ }
+
+ public class ExtensionDescriptorLite : IFieldDescriptorLite {
+ private readonly string fullName;
+ private readonly IEnumLiteMap enumTypeMap;
+ private readonly int number;
+ private readonly FieldType type;
+ private readonly bool isRepeated;
+ private readonly bool isPacked;
+ private readonly MappedType mapType;
+ private readonly object defaultValue;
+
+ public ExtensionDescriptorLite(string fullName, IEnumLiteMap enumTypeMap, int number, FieldType type, object defaultValue, bool isRepeated, bool isPacked) {
+ this.fullName = fullName;
+ this.enumTypeMap = enumTypeMap;
+ this.number = number;
+ this.type = type;
+ this.mapType = FieldMappingAttribute.MappedTypeFromFieldType(type);
+ this.isRepeated = isRepeated;
+ this.isPacked = isPacked;
+ this.defaultValue = defaultValue;
+ }
+
+ public string FullName { get { return fullName; } }
+
+ public bool IsRepeated {
+ get { return isRepeated; }
+ }
+
+ public bool IsRequired {
+ get { return false; }
+ }
+
+ public bool IsPacked {
+ get { return isPacked; }
+ }
+
+ public bool IsExtension {
+ get { return true; }
+ }
+
+ /// <summary>
+ /// This is not supported and assertions are made to ensure this does not exist on extensions of Lite types
+ /// </summary>
+ public bool MessageSetWireFormat {
+ get { return false; }
+ }
+
+ public int FieldNumber {
+ get { return number; }
+ }
+
+ public IEnumLiteMap EnumType {
+ get { return enumTypeMap; }
+ }
+
+ public FieldType FieldType {
+ get { return type; }
+ }
+
+ public MappedType MappedType {
+ get { return mapType; }
+ }
+
+ public object DefaultValue {
+ get { return defaultValue; }
+ }
+
+ public int CompareTo(IFieldDescriptorLite other) {
+ return FieldNumber.CompareTo(other.FieldNumber);
+ }
+ }
+
+ public class GeneratedRepeatExtensionLite<TContainingType, TExtensionType> : GeneratedExtensionLite<TContainingType, IList<TExtensionType>>
+ where TContainingType : IMessageLite {
+ public GeneratedRepeatExtensionLite(string fullName, TContainingType containingTypeDefaultInstance,
+ IMessageLite messageDefaultInstance, IEnumLiteMap enumTypeMap, int number, FieldType type, bool isPacked) :
+ base(fullName, containingTypeDefaultInstance, new List<TExtensionType>(), messageDefaultInstance, enumTypeMap, number, type, isPacked) {
+ }
+
+ public override object ToReflectionType(object value) {
+ IList<object> result = new List<object>();
+ foreach (object element in (IEnumerable) value) {
+ result.Add(SingularToReflectionType(element));
+ }
+ return result;
+ }
+
+ public override object FromReflectionType(object value) {
+ // Must convert the whole list.
+ List<TExtensionType> result = new List<TExtensionType>();
+ foreach (object element in (IEnumerable)value) {
+ result.Add((TExtensionType)SingularFromReflectionType(element));
+ }
+ return result;
+ }
+ }
+
+ public class GeneratedExtensionLite<TContainingType, TExtensionType> : IGeneratedExtensionLite
+ where TContainingType : IMessageLite {
+
+ private readonly TContainingType containingTypeDefaultInstance;
+ private readonly TExtensionType defaultValue;
+ private readonly IMessageLite messageDefaultInstance;
+ private readonly ExtensionDescriptorLite descriptor;
+
+ // We can't always initialize a GeneratedExtension when we first construct
+ // it due to initialization order difficulties (namely, the default
+ // instances may not have been constructed yet). So, we construct an
+ // uninitialized GeneratedExtension once, then call internalInit() on it
+ // later. Generated code will always call internalInit() on all extensions
+ // as part of the static initialization code, and internalInit() throws an
+ // exception if called more than once, so this method is useless to users.
+ protected GeneratedExtensionLite(
+ TContainingType containingTypeDefaultInstance,
+ TExtensionType defaultValue,
+ IMessageLite messageDefaultInstance,
+ ExtensionDescriptorLite descriptor) {
+ this.containingTypeDefaultInstance = containingTypeDefaultInstance;
+ this.messageDefaultInstance = messageDefaultInstance;
+ this.defaultValue = defaultValue;
+ this.descriptor = descriptor;
+ }
+
+ /** For use by generated code only. */
+ public GeneratedExtensionLite(
+ string fullName,
+ TContainingType containingTypeDefaultInstance,
+ TExtensionType defaultValue,
+ IMessageLite messageDefaultInstance,
+ IEnumLiteMap enumTypeMap,
+ int number,
+ FieldType type)
+ : this(containingTypeDefaultInstance, defaultValue, messageDefaultInstance,
+ new ExtensionDescriptorLite(fullName, enumTypeMap, number, type, defaultValue,
+ false /* isRepeated */, false /* isPacked */)) {
+ }
+
+ private static readonly IList<object> Empty = new object[0];
+ /** Repeating fields: For use by generated code only. */
+ protected GeneratedExtensionLite(
+ string fullName,
+ TContainingType containingTypeDefaultInstance,
+ TExtensionType defaultValue,
+ IMessageLite messageDefaultInstance,
+ IEnumLiteMap enumTypeMap,
+ int number,
+ FieldType type,
+ bool isPacked)
+ : this(containingTypeDefaultInstance, defaultValue, messageDefaultInstance,
+ new ExtensionDescriptorLite(fullName, enumTypeMap, number, type, Empty,
+ true /* isRepeated */, isPacked)) {
+ }
+
+ /// <summary>
+ /// Returns information about this extension
+ /// </summary>
+ public IFieldDescriptorLite Descriptor {
+ get { return descriptor; }
+ }
+
+ /// <summary>
+ /// Returns the default value for this extension
+ /// </summary>
+ public TExtensionType DefaultValue {
+ get { return defaultValue; }
+ }
+
+ /// <summary>
+ /// used for the extension registry
+ /// </summary>
+ object IGeneratedExtensionLite.ContainingType {
+ get { return ContainingTypeDefaultInstance; }
+ }
+ /**
+ * Default instance of the type being extended, used to identify that type.
+ */
+ public TContainingType ContainingTypeDefaultInstance {
+ get {
+ return containingTypeDefaultInstance;
+ }
+ }
+
+ /** Get the field number. */
+ public int Number {
+ get {
+ return descriptor.FieldNumber;
+ }
+ }
+ /**
+ * If the extension is an embedded message, this is the default instance of
+ * that type.
+ */
+ public IMessageLite MessageDefaultInstance {
+ get {
+ return messageDefaultInstance;
+ }
+ }
+
+ /// <summary>
+ /// Converts from the type used by the native accessors to the type
+ /// used by reflection accessors. For example, the reflection accessors
+ /// for enums use EnumValueDescriptors but the native accessors use
+ /// the generated enum type.
+ /// </summary>
+ public virtual object ToReflectionType(object value) {
+ return SingularToReflectionType(value);
+ }
+
+ /// <summary>
+ /// Like ToReflectionType(object) but for a single element.
+ /// </summary>
+ public object SingularToReflectionType(object value) {
+ return descriptor.MappedType == MappedType.Enum
+ ? descriptor.EnumType.FindValueByNumber((int)value)
+ : value;
+ }
+
+ public virtual object FromReflectionType(object value) {
+ return SingularFromReflectionType(value);
+ }
+
+ public object SingularFromReflectionType(object value) {
+ switch (Descriptor.MappedType) {
+ case MappedType.Message:
+ if (value is TExtensionType) {
+ return value;
+ } else {
+ // It seems the copy of the embedded message stored inside the
+ // extended message is not of the exact type the user was
+ // expecting. This can happen if a user defines a
+ // GeneratedExtension manually and gives it a different type.
+ // This should not happen in normal use. But, to be nice, we'll
+ // copy the message to whatever type the caller was expecting.
+ return MessageDefaultInstance.WeakCreateBuilderForType()
+ .WeakMergeFrom((IMessageLite)value).WeakBuild();
+ }
+ case MappedType.Enum:
+ // Just return a boxed int - that can be unboxed to the enum
+ IEnumLite enumValue = (IEnumLite)value;
+ return enumValue.Number;
+ default:
+ return value;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/ProtocolBuffers/GeneratedMessage.cs b/src/ProtocolBuffers/GeneratedMessage.cs
index d60f2b9c..fe1188b6 100644
--- a/src/ProtocolBuffers/GeneratedMessage.cs
+++ b/src/ProtocolBuffers/GeneratedMessage.cs
@@ -99,13 +99,13 @@ namespace Google.ProtocolBuffers {
if (field.IsRepeated) {
// We know it's an IList<T>, but not the exact type - so
// IEnumerable is the best we can do. (C# generics aren't covariant yet.)
- foreach (IMessage element in (IEnumerable) this[field]) {
+ foreach (IMessageLite element in (IEnumerable) this[field]) {
if (!element.IsInitialized) {
return false;
}
}
} else {
- if (HasField(field) && !((IMessage) this[field]).IsInitialized) {
+ if (HasField(field) && !((IMessageLite) this[field]).IsInitialized) {
return false;
}
}
diff --git a/src/ProtocolBuffers/GeneratedMessageLite.cs b/src/ProtocolBuffers/GeneratedMessageLite.cs
new file mode 100644
index 00000000..b2a009c4
--- /dev/null
+++ b/src/ProtocolBuffers/GeneratedMessageLite.cs
@@ -0,0 +1,132 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// 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.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Collections;
+using System.Globalization;
+using Google.ProtocolBuffers.Descriptors;
+
+namespace Google.ProtocolBuffers {
+
+ /// <summary>
+ /// All generated protocol message classes extend this class. It implements
+ /// most of the IMessage interface using reflection. Users
+ /// can ignore this class as an implementation detail.
+ /// </summary>
+ public abstract class GeneratedMessageLite<TMessage, TBuilder> : AbstractMessageLite<TMessage, TBuilder>
+ where TMessage : GeneratedMessageLite<TMessage, TBuilder>
+ where TBuilder : GeneratedBuilderLite<TMessage, TBuilder> {
+
+ protected abstract TMessage ThisMessage { get; }
+
+ public sealed override string ToString() {
+ using (System.IO.StringWriter wtr = new System.IO.StringWriter()) {
+ PrintTo(wtr);
+ return wtr.ToString();
+ }
+ }
+
+ /// <summary>
+ /// PrintTo() helper methods for Lite Runtime
+ /// </summary>
+ protected static void PrintField<T>(string name, IList<T> value, System.IO.TextWriter writer) {
+ foreach (T item in value)
+ PrintField(name, true, (object)item, writer);
+ }
+ /// <summary>
+ /// PrintTo() helper methods for Lite Runtime
+ /// </summary>
+ protected static void PrintField(string name, bool hasValue, object value, System.IO.TextWriter writer) {
+ if (!hasValue) return;
+ if (value is IMessageLite) {
+ writer.WriteLine("{0} {{", name);
+ ((IMessageLite)value).PrintTo(writer);
+ writer.WriteLine("}");
+ } else if (value is ByteString || value is String) {
+ writer.Write("{0}: \"", name);
+ if(value is String)
+ EscapeBytes( System.Text.Encoding.UTF8.GetBytes((string)value), writer);
+ else
+ EscapeBytes(((ByteString)value), writer);
+ writer.WriteLine("\"");
+ } else if (value is bool) {
+ writer.WriteLine("{0}: {1}", name, (bool)value ? "true" : "false");
+ } else if (value is IEnumLite) {
+ writer.WriteLine("{0}: {1}", name, ((IEnumLite)value).Name);
+ }
+ else {
+ writer.WriteLine("{0}: {1}", name, ((IConvertible)value).ToString(CultureInfo.InvariantCulture));
+ }
+ }
+
+ /// <summary>
+ /// COPIED from TextFormat
+ /// Escapes bytes in the format used in protocol buffer text format, which
+ /// is the same as the format used for C string literals. All bytes
+ /// that are not printable 7-bit ASCII characters are escaped, as well as
+ /// backslash, single-quote, and double-quote characters. Characters for
+ /// which no defined short-hand escape sequence is defined will be escaped
+ /// using 3-digit octal sequences.
+ /// The returned value is guaranteed to be entirely ASCII.
+ /// </summary>
+ private static void EscapeBytes(IEnumerable<byte> input, System.IO.TextWriter writer) {
+ foreach (byte b in input) {
+ switch (b) {
+ // C# does not use \a or \v
+ case 0x07: writer.Write("\\a"); break;
+ case (byte)'\b': writer.Write("\\b"); break;
+ case (byte)'\f': writer.Write("\\f"); break;
+ case (byte)'\n': writer.Write("\\n"); break;
+ case (byte)'\r': writer.Write("\\r"); break;
+ case (byte)'\t': writer.Write("\\t"); break;
+ case 0x0b: writer.Write("\\v"); break;
+ case (byte)'\\': writer.Write("\\\\"); break;
+ case (byte)'\'': writer.Write("\\\'"); break;
+ case (byte)'"': writer.Write("\\\""); break;
+ default:
+ if (b >= 0x20 && b < 128) {
+ writer.Write((char)b);
+ } else {
+ writer.Write('\\');
+ writer.Write((char)('0' + ((b >> 6) & 3)));
+ writer.Write((char)('0' + ((b >> 3) & 7)));
+ writer.Write((char)('0' + (b & 7)));
+ }
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/src/ProtocolBuffers/IBuilder.cs b/src/ProtocolBuffers/IBuilder.cs
index b1aa4fb1..c4a1c609 100644
--- a/src/ProtocolBuffers/IBuilder.cs
+++ b/src/ProtocolBuffers/IBuilder.cs
@@ -47,12 +47,12 @@ namespace Google.ProtocolBuffers {
/// use explicit interface implemenation for the non-generic form. This mirrors
/// how IEnumerable and IEnumerable&lt;T&gt; work.
/// </summary>
- public interface IBuilder {
+ public interface IBuilder : IBuilderLite {
/// <summary>
/// Returns true iff all required fields in the message and all
/// embedded messages are set.
/// </summary>
- bool IsInitialized { get; }
+ new bool IsInitialized { get; }
/// <summary>
/// Only present in the nongeneric interface - useful for tests, but
@@ -119,17 +119,17 @@ namespace Google.ProtocolBuffers {
#region Methods which are like those of the generic form, but without any knowledge of the type parameters
IBuilder WeakAddRepeatedField(FieldDescriptor field, object value);
- IBuilder WeakClear();
+ new IBuilder WeakClear();
IBuilder WeakClearField(FieldDescriptor field);
IBuilder WeakMergeFrom(IMessage message);
- IBuilder WeakMergeFrom(ByteString data);
- IBuilder WeakMergeFrom(ByteString data, ExtensionRegistry registry);
- IBuilder WeakMergeFrom(CodedInputStream input);
- IBuilder WeakMergeFrom(CodedInputStream input, ExtensionRegistry registry);
- IMessage WeakBuild();
- IMessage WeakBuildPartial();
- IBuilder WeakClone();
- IMessage WeakDefaultInstanceForType { get; }
+ new IBuilder WeakMergeFrom(ByteString data);
+ new IBuilder WeakMergeFrom(ByteString data, ExtensionRegistry registry);
+ new IBuilder WeakMergeFrom(CodedInputStream input);
+ new IBuilder WeakMergeFrom(CodedInputStream input, ExtensionRegistry registry);
+ new IMessage WeakBuild();
+ new IMessage WeakBuildPartial();
+ new IBuilder WeakClone();
+ new IMessage WeakDefaultInstanceForType { get; }
#endregion
}
@@ -139,7 +139,7 @@ namespace Google.ProtocolBuffers {
/// </summary>
/// <typeparam name="TMessage">Type of message</typeparam>
/// <typeparam name="TBuilder">Type of builder</typeparam>
- public interface IBuilder<TMessage, TBuilder> : IBuilder
+ public interface IBuilder<TMessage, TBuilder> : IBuilder, IBuilderLite<TMessage, TBuilder>
where TMessage : IMessage<TMessage, TBuilder>
where TBuilder : IBuilder<TMessage, TBuilder> {
@@ -148,22 +148,7 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// Resets all fields to their default values.
/// </summary>
- TBuilder Clear();
-
- /// <summary>
- /// Merge the specified other message into the message being
- /// built. Merging occurs as follows. For each field:
- /// For singular primitive fields, if the field is set in <paramref name="other"/>,
- /// then <paramref name="other"/>'s value overwrites the value in this message.
- /// For singular message fields, if the field is set in <paramref name="other"/>,
- /// it is merged into the corresponding sub-message of this message using the same
- /// merging rules.
- /// For repeated fields, the elements in <paramref name="other"/> are concatenated
- /// with the elements in this message.
- /// </summary>
- /// <param name="other"></param>
- /// <returns></returns>
- TBuilder MergeFrom(TMessage other);
+ new TBuilder Clear();
/// <summary>
/// Merge the specified other message which may be a different implementation of
@@ -180,19 +165,19 @@ namespace Google.ProtocolBuffers {
/// <exception cref="UninitializedMessageException">the message
/// is missing one or more required fields; use BuildPartial to bypass
/// this check</exception>
- TMessage Build();
+ new TMessage Build();
/// <summary>
/// Like Build(), but does not throw an exception if the message is missing
/// required fields. Instead, a partial message is returned.
/// </summary>
- TMessage BuildPartial();
+ new TMessage BuildPartial();
/// <summary>
/// Clones this builder.
/// TODO(jonskeet): Explain depth of clone.
/// </summary>
- TBuilder Clone();
+ new TBuilder Clone();
/// <summary>
/// Parses a message of this type from the input and merges it with this
@@ -213,7 +198,7 @@ namespace Google.ProtocolBuffers {
/// Use BuildPartial to build, which ignores missing required fields.
/// </list>
/// </remarks>
- TBuilder MergeFrom(CodedInputStream input);
+ new TBuilder MergeFrom(CodedInputStream input);
/// <summary>
/// Like MergeFrom(CodedInputStream), but also parses extensions.
@@ -221,13 +206,13 @@ namespace Google.ProtocolBuffers {
/// in <paramref name="extensionRegistry"/>. Extensions not in the registry
/// will be treated as unknown fields.
/// </summary>
- TBuilder MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry);
+ new TBuilder MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry);
/// <summary>
/// Get's the message's type's default instance.
/// <see cref="IMessage{TMessage}.DefaultInstanceForType" />
/// </summary>
- TMessage DefaultInstanceForType { get; }
+ new TMessage DefaultInstanceForType { get; }
/// <summary>
/// Clears the field. This is exactly equivalent to calling the generated
@@ -258,12 +243,12 @@ namespace Google.ProtocolBuffers {
/// write messages in this format.
/// </summary>
/// <param name="input"></param>
- TBuilder MergeDelimitedFrom(Stream input);
+ new TBuilder MergeDelimitedFrom(Stream input);
/// <summary>
/// Like MergeDelimitedFrom(Stream) but supporting extensions.
/// </summary>
- TBuilder MergeDelimitedFrom(Stream input, ExtensionRegistry extensionRegistry);
+ new TBuilder MergeDelimitedFrom(Stream input, ExtensionRegistry extensionRegistry);
#region Convenience methods
/// <summary>
@@ -271,28 +256,28 @@ namespace Google.ProtocolBuffers {
/// it with the message being built. This is just a small wrapper around
/// MergeFrom(CodedInputStream).
/// </summary>
- TBuilder MergeFrom(ByteString data);
+ new TBuilder MergeFrom(ByteString data);
/// <summary>
/// Parse <paramref name="data"/> as a message of this type and merge
/// it with the message being built. This is just a small wrapper around
- /// MergeFrom(CodedInputStream, ExtensionRegistry).
+ /// MergeFrom(CodedInputStream, extensionRegistry).
/// </summary>
- TBuilder MergeFrom(ByteString data, ExtensionRegistry extensionRegistry);
+ new TBuilder MergeFrom(ByteString data, ExtensionRegistry extensionRegistry);
/// <summary>
/// Parse <paramref name="data"/> as a message of this type and merge
/// it with the message being built. This is just a small wrapper around
/// MergeFrom(CodedInputStream).
/// </summary>
- TBuilder MergeFrom(byte[] data);
+ new TBuilder MergeFrom(byte[] data);
/// <summary>
/// Parse <paramref name="data"/> as a message of this type and merge
/// it with the message being built. This is just a small wrapper around
- /// MergeFrom(CodedInputStream, ExtensionRegistry).
+ /// MergeFrom(CodedInputStream, extensionRegistry).
/// </summary>
- TBuilder MergeFrom(byte[] data, ExtensionRegistry extensionRegistry);
+ new TBuilder MergeFrom(byte[] data, ExtensionRegistry extensionRegistry);
/// <summary>
/// Parse <paramref name="input"/> as a message of this type and merge
@@ -304,14 +289,14 @@ namespace Google.ProtocolBuffers {
/// 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);
+ new TBuilder MergeFrom(Stream input);
/// <summary>
/// Parse <paramref name="input"/> as a message of this type and merge
/// it with the message being built. This is just a small wrapper around
- /// MergeFrom(CodedInputStream, ExtensionRegistry).
+ /// MergeFrom(CodedInputStream, extensionRegistry).
/// </summary>
- TBuilder MergeFrom(Stream input, ExtensionRegistry extensionRegistry);
+ new TBuilder MergeFrom(Stream input, ExtensionRegistry extensionRegistry);
#endregion
}
}
diff --git a/src/ProtocolBuffers/IBuilderLite.cs b/src/ProtocolBuffers/IBuilderLite.cs
new file mode 100644
index 00000000..e91d44bc
--- /dev/null
+++ b/src/ProtocolBuffers/IBuilderLite.cs
@@ -0,0 +1,210 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// 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.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Google.ProtocolBuffers {
+
+ /// <summary>
+ /// Non-generic interface for all members whose signatures don't require knowledge of
+ /// the type being built. The generic interface extends this one. Some methods return
+ /// either an IBuilder or an IMessage; in these cases the generic interface redeclares
+ /// the same method with a type-specific signature. Implementations are encouraged to
+ /// use explicit interface implemenation for the non-generic form. This mirrors
+ /// how IEnumerable and IEnumerable&lt;T&gt; work.
+ /// </summary>
+ public interface IBuilderLite {
+ /// <summary>
+ /// Returns true iff all required fields in the message and all
+ /// embedded messages are set.
+ /// </summary>
+ bool IsInitialized { get; }
+
+ IBuilderLite WeakClear();
+ IBuilderLite WeakMergeFrom(IMessageLite message);
+ IBuilderLite WeakMergeFrom(ByteString data);
+ IBuilderLite WeakMergeFrom(ByteString data, ExtensionRegistry registry);
+ IBuilderLite WeakMergeFrom(CodedInputStream input);
+ IBuilderLite WeakMergeFrom(CodedInputStream input, ExtensionRegistry registry);
+ IMessageLite WeakBuild();
+ IMessageLite WeakBuildPartial();
+ IBuilderLite WeakClone();
+ IMessageLite WeakDefaultInstanceForType { get; }
+ }
+
+ /// <summary>
+ /// Interface implemented by Protocol Message builders.
+ /// TODO(jonskeet): Consider "SetXXX" methods returning the builder, as well as the properties.
+ /// </summary>
+ /// <typeparam name="TMessage">Type of message</typeparam>
+ /// <typeparam name="TBuilder">Type of builder</typeparam>
+ public interface IBuilderLite<TMessage, TBuilder> : IBuilderLite
+ where TMessage : IMessageLite<TMessage, TBuilder>
+ where TBuilder : IBuilderLite<TMessage, TBuilder> {
+
+ /// <summary>
+ /// Resets all fields to their default values.
+ /// </summary>
+ TBuilder Clear();
+
+ /// <summary>
+ /// Merge the specified other message which may be a different implementation of
+ /// the same message descriptor.
+ /// </summary>
+ TBuilder MergeFrom(IMessageLite other);
+
+ /// <summary>
+ /// Constructs the final message. Once this is called, this Builder instance
+ /// is no longer valid, and calling any other method may throw a
+ /// NullReferenceException. If you need to continue working with the builder
+ /// after calling Build, call Clone first.
+ /// </summary>
+ /// <exception cref="UninitializedMessageException">the message
+ /// is missing one or more required fields; use BuildPartial to bypass
+ /// this check</exception>
+ TMessage Build();
+
+ /// <summary>
+ /// Like Build(), but does not throw an exception if the message is missing
+ /// required fields. Instead, a partial message is returned.
+ /// </summary>
+ TMessage BuildPartial();
+
+ /// <summary>
+ /// Clones this builder.
+ /// TODO(jonskeet): Explain depth of clone.
+ /// </summary>
+ TBuilder Clone();
+
+ /// <summary>
+ /// Parses a message of this type from the input and merges it with this
+ /// message, as if using MergeFrom(IMessage&lt;T&gt;).
+ /// </summary>
+ /// <remarks>
+ /// Warning: This does not verify that all required fields are present
+ /// in the input message. If you call Build() without setting all
+ /// required fields, it will throw an UninitializedMessageException.
+ /// There are a few good ways to deal with this:
+ /// <list>
+ /// <item>Call IsInitialized to verify to verify that all required fields are
+ /// set before building.</item>
+ /// <item>Parse the message separately using one of the static ParseFrom
+ /// methods, then use MergeFrom(IMessage&lt;T&gt;) to merge it with
+ /// this one. ParseFrom will throw an InvalidProtocolBufferException
+ /// (an IOException) if some required fields are missing.
+ /// Use BuildPartial to build, which ignores missing required fields.
+ /// </list>
+ /// </remarks>
+ TBuilder MergeFrom(CodedInputStream input);
+
+ /// <summary>
+ /// Like MergeFrom(CodedInputStream), but also parses extensions.
+ /// The extensions that you want to be able to parse must be registered
+ /// in <paramref name="extensionRegistry"/>. Extensions not in the registry
+ /// will be treated as unknown fields.
+ /// </summary>
+ TBuilder MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry);
+
+ /// <summary>
+ /// Get's the message's type's default instance.
+ /// <see cref="IMessageLite{TMessage}.DefaultInstanceForType" />
+ /// </summary>
+ TMessage DefaultInstanceForType { get; }
+
+ /// <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>
+ /// Parse <paramref name="data"/> as a message of this type and merge
+ /// it with the message being built. This is just a small wrapper around
+ /// MergeFrom(CodedInputStream).
+ /// </summary>
+ TBuilder MergeFrom(ByteString data);
+
+ /// <summary>
+ /// Parse <paramref name="data"/> as a message of this type and merge
+ /// it with the message being built. This is just a small wrapper around
+ /// MergeFrom(CodedInputStream, ExtensionRegistry).
+ /// </summary>
+ TBuilder MergeFrom(ByteString data, ExtensionRegistry extensionRegistry);
+
+ /// <summary>
+ /// Parse <paramref name="data"/> as a message of this type and merge
+ /// it with the message being built. This is just a small wrapper around
+ /// MergeFrom(CodedInputStream).
+ /// </summary>
+ TBuilder MergeFrom(byte[] data);
+
+ /// <summary>
+ /// Parse <paramref name="data"/> as a message of this type and merge
+ /// it with the message being built. This is just a small wrapper around
+ /// MergeFrom(CodedInputStream, ExtensionRegistry).
+ /// </summary>
+ TBuilder MergeFrom(byte[] data, ExtensionRegistry extensionRegistry);
+
+ /// <summary>
+ /// Parse <paramref name="input"/> as a message of this type and merge
+ /// it with the message being built. This is just a small wrapper around
+ /// 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. 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);
+
+ /// <summary>
+ /// Parse <paramref name="input"/> as a message of this type and merge
+ /// it with the message being built. This is just a small wrapper around
+ /// MergeFrom(CodedInputStream, ExtensionRegistry).
+ /// </summary>
+ TBuilder MergeFrom(Stream input, ExtensionRegistry extensionRegistry);
+ #endregion
+ }
+}
diff --git a/src/ProtocolBuffers/IMessage.cs b/src/ProtocolBuffers/IMessage.cs
index ec955c6d..4d37a8d2 100644
--- a/src/ProtocolBuffers/IMessage.cs
+++ b/src/ProtocolBuffers/IMessage.cs
@@ -43,7 +43,7 @@ namespace Google.ProtocolBuffers {
/// Non-generic interface used for all parts of the API which don't require
/// any type knowledge.
/// </summary>
- public interface IMessage {
+ public interface IMessage : IMessageLite {
/// <summary>
/// Returns the message's type's descriptor. This differs from the
/// Descriptor property of each generated message class in that this
@@ -110,7 +110,7 @@ namespace Google.ProtocolBuffers {
/// Returns true iff all required fields in the message and all embedded
/// messages are set.
/// </summary>
- bool IsInitialized { get; }
+ new bool IsInitialized { get; }
/// <summary>
/// Serializes the message and writes it to the given output stream.
@@ -124,7 +124,7 @@ namespace Google.ProtocolBuffers {
/// 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);
+ new void WriteTo(CodedOutputStream output);
/// <summary>
/// Like WriteTo(Stream) but writes the size of the message as a varint before
@@ -134,13 +134,13 @@ namespace Google.ProtocolBuffers {
/// YourMessageType.ParseDelimitedFrom(Stream) to parse messages written by this method.
/// </summary>
/// <param name="output"></param>
- void WriteDelimitedTo(Stream output);
+ new 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.
/// </summary>
- int SerializedSize { get; }
+ new int SerializedSize { get; }
#region Comparison and hashing
/// <summary>
@@ -149,13 +149,13 @@ namespace Google.ProtocolBuffers {
/// (as defined by DescriptorForType) and has identical values
/// for all its fields.
/// </summary>
- bool Equals(object other);
+ new bool Equals(object other);
/// <summary>
/// Returns the hash code value for this message.
/// TODO(jonskeet): Specify the hash algorithm, but better than the Java one!
/// </summary>
- int GetHashCode();
+ new int GetHashCode();
#endregion
#region Convenience methods
@@ -163,19 +163,19 @@ namespace Google.ProtocolBuffers {
/// Converts the message to a string in protocol buffer text format.
/// This is just a trivial wrapper around TextFormat.PrintToString.
/// </summary>
- string ToString();
+ new string ToString();
/// <summary>
/// Serializes the message to a ByteString. This is a trivial wrapper
/// around WriteTo(CodedOutputStream).
/// </summary>
- ByteString ToByteString();
+ new ByteString ToByteString();
/// <summary>
/// Serializes the message to a byte array. This is a trivial wrapper
/// around WriteTo(CodedOutputStream).
/// </summary>
- byte[] ToByteArray();
+ new byte[] ToByteArray();
/// <summary>
/// Serializes the message and writes it to the given stream.
@@ -183,7 +183,7 @@ namespace Google.ProtocolBuffers {
/// does not flush or close the stream.
/// </summary>
/// <param name="output"></param>
- void WriteTo(Stream output);
+ new void WriteTo(Stream output);
#endregion
/// <summary>
@@ -191,19 +191,19 @@ namespace Google.ProtocolBuffers {
/// is typically implemented by strongly typed messages by just returning
/// the result of CreateBuilderForType.
/// </summary>
- IBuilder WeakCreateBuilderForType();
+ new IBuilder WeakCreateBuilderForType();
/// <summary>
/// Creates a builder with the same contents as this message. This
/// is typically implemented by strongly typed messages by just returning
/// the result of ToBuilder.
/// </summary>
- IBuilder WeakToBuilder();
+ new IBuilder WeakToBuilder();
- IMessage WeakDefaultInstanceForType { get; }
+ new IMessage WeakDefaultInstanceForType { get; }
}
- public interface IMessage<TMessage> : IMessage {
+ public interface IMessage<TMessage> : IMessage, IMessageLite<TMessage> {
/// <summary>
/// Returns an instance of this message type with all fields set to
/// their default values. This may or may not be a singleton. This differs
@@ -211,26 +211,26 @@ namespace Google.ProtocolBuffers {
/// method is an abstract method of IMessage whereas DefaultInstance is
/// a static property of a specific class. They return the same thing.
/// </summary>
- TMessage DefaultInstanceForType { get; }
+ new TMessage DefaultInstanceForType { get; }
}
/// <summary>
/// Type-safe interface for all generated messages to implement.
/// </summary>
- public interface IMessage<TMessage, TBuilder> : IMessage<TMessage>
+ public interface IMessage<TMessage, TBuilder> : IMessage<TMessage>, IMessageLite<TMessage, TBuilder>
where TMessage : IMessage<TMessage, TBuilder>
where TBuilder : IBuilder<TMessage, TBuilder> {
#region Builders
/// <summary>
/// Constructs a new builder for a message of the same type as this message.
/// </summary>
- TBuilder CreateBuilderForType();
+ new TBuilder CreateBuilderForType();
/// <summary>
/// Creates a builder with the same contents as this current instance.
/// This is typically implemented by strongly typed messages by just
/// returning the result of ToBuilder().
/// </summary>
- TBuilder ToBuilder();
+ new TBuilder ToBuilder();
#endregion
}
}
diff --git a/src/ProtocolBuffers/IMessageLite.cs b/src/ProtocolBuffers/IMessageLite.cs
new file mode 100644
index 00000000..48660882
--- /dev/null
+++ b/src/ProtocolBuffers/IMessageLite.cs
@@ -0,0 +1,179 @@
+#region Copyright notice and license
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://github.com/jskeet/dotnet-protobufs/
+// Original C++/Java/Python code:
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// 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.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Google.ProtocolBuffers {
+
+ /// <summary>
+ /// Non-generic interface used for all parts of the API which don't require
+ /// any type knowledge.
+ /// </summary>
+ public interface IMessageLite {
+
+ /// <summary>
+ /// Returns true iff all required fields in the message and all embedded
+ /// messages are set.
+ /// </summary>
+ bool IsInitialized { get; }
+
+ /// <summary>
+ /// Serializes the message and writes it to the given output stream.
+ /// This does not flush or close the stream.
+ /// </summary>
+ /// <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.
+ /// </summary>
+ int SerializedSize { get; }
+
+ #region Comparison and hashing
+ /// <summary>
+ /// Compares the specified object with this message for equality.
+ /// Returns true iff the given object is a message of the same type
+ /// (as defined by DescriptorForType) and has identical values
+ /// for all its fields.
+ /// </summary>
+ bool Equals(object other);
+
+ /// <summary>
+ /// Returns the hash code value for this message.
+ /// TODO(jonskeet): Specify the hash algorithm, but better than the Java one!
+ /// </summary>
+ int GetHashCode();
+ #endregion
+
+ #region Convenience methods
+ /// <summary>
+ /// Converts the message to a string in protocol buffer text format.
+ /// This is just a trivial wrapper around TextFormat.PrintToString.
+ /// </summary>
+ string ToString();
+
+ /// <summary>
+ /// Converts the message to a string.
+ /// </summary>
+ void PrintTo(TextWriter writer);
+
+ /// <summary>
+ /// Serializes the message to a ByteString. This is a trivial wrapper
+ /// around WriteTo(CodedOutputStream).
+ /// </summary>
+ ByteString ToByteString();
+
+ /// <summary>
+ /// Serializes the message to a byte array. This is a trivial wrapper
+ /// around WriteTo(CodedOutputStream).
+ /// </summary>
+ byte[] ToByteArray();
+
+ /// <summary>
+ /// Serializes the message and writes it to the given stream.
+ /// This is just a wrapper around WriteTo(CodedOutputStream). This
+ /// does not flush or close the stream.
+ /// </summary>
+ /// <param name="output"></param>
+ void WriteTo(Stream output);
+ #endregion
+
+ /// <summary>
+ /// Creates a builder for the type, but in a weakly typed manner. This
+ /// is typically implemented by strongly typed messages by just returning
+ /// the result of CreateBuilderForType.
+ /// </summary>
+ IBuilderLite WeakCreateBuilderForType();
+
+ /// <summary>
+ /// Creates a builder with the same contents as this message. This
+ /// is typically implemented by strongly typed messages by just returning
+ /// the result of ToBuilder.
+ /// </summary>
+ IBuilderLite WeakToBuilder();
+
+ IMessageLite WeakDefaultInstanceForType { get; }
+ }
+
+ public interface IMessageLite<TMessage> : IMessageLite {
+ /// <summary>
+ /// Returns an instance of this message type with all fields set to
+ /// their default values. This may or may not be a singleton. This differs
+ /// from the DefaultInstance property of each generated message class in that this
+ /// method is an abstract method of IMessage whereas DefaultInstance is
+ /// a static property of a specific class. They return the same thing.
+ /// </summary>
+ TMessage DefaultInstanceForType { get; }
+ }
+
+ /// <summary>
+ /// Type-safe interface for all generated messages to implement.
+ /// </summary>
+ public interface IMessageLite<TMessage, TBuilder> : IMessageLite<TMessage>
+ where TMessage : IMessageLite<TMessage, TBuilder>
+ where TBuilder : IBuilderLite<TMessage, TBuilder> {
+ #region Builders
+ /// <summary>
+ /// Constructs a new builder for a message of the same type as this message.
+ /// </summary>
+ TBuilder CreateBuilderForType();
+ /// <summary>
+ /// Creates a builder with the same contents as this current instance.
+ /// This is typically implemented by strongly typed messages by just
+ /// returning the result of ToBuilder().
+ /// </summary>
+ TBuilder ToBuilder();
+ #endregion
+ }
+}
diff --git a/src/ProtocolBuffers/Properties/AssemblyInfo.cs b/src/ProtocolBuffers/Properties/AssemblyInfo.cs
index a1047370..e86a2f15 100644
--- a/src/ProtocolBuffers/Properties/AssemblyInfo.cs
+++ b/src/ProtocolBuffers/Properties/AssemblyInfo.cs
@@ -74,6 +74,12 @@ using System.Runtime.CompilerServices;
"72f738140072bb69990bc4f98a21365de2c105e848974a3d210e938b0a56103c0662901efd6b78"+
"0ee6dbe977923d46a8fda18fb25c65dd73b149a5cd9f3100668b56649932dadd8cf5be52eb1dce"+
"ad5cedbf")]
+[assembly: InternalsVisibleTo("Google.ProtocolBuffersLite.Test,PublicKey=" +
+"00240000048000009400000006020000002400005253413100040000010001008179f2dd31a648" +
+"2a2359dbe33e53701167a888e7c369a9ae3210b64f93861d8a7d286447e58bc167e3d99483beda" +
+"72f738140072bb69990bc4f98a21365de2c105e848974a3d210e938b0a56103c0662901efd6b78" +
+"0ee6dbe977923d46a8fda18fb25c65dd73b149a5cd9f3100668b56649932dadd8cf5be52eb1dce" +
+"ad5cedbf")]
[assembly: InternalsVisibleTo("ProtoGen,PublicKey=" +
"00240000048000009400000006020000002400005253413100040000010001006d739020e13bdc" +
"038e86fa8aa5e1b13aae65d3ae79d622816c6067ab5b6955be50cc887130117582349208c13a55" +
diff --git a/src/ProtocolBuffers/ProtocolBuffers.csproj b/src/ProtocolBuffers/ProtocolBuffers.csproj
index cff758e4..715afe87 100644
--- a/src/ProtocolBuffers/ProtocolBuffers.csproj
+++ b/src/ProtocolBuffers/ProtocolBuffers.csproj
@@ -80,10 +80,18 @@
<ItemGroup>
<Reference Include="mscorlib" />
<Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="AbstractBuilder.cs" />
+ <Compile Include="AbstractBuilderLite.cs">
+ <SubType>Code</SubType>
+ </Compile>
<Compile Include="AbstractMessage.cs" />
+ <Compile Include="AbstractMessageLite.cs">
+ <SubType>Code</SubType>
+ </Compile>
<Compile Include="ByteString.cs" />
<Compile Include="Collections\Enumerables.cs" />
<Compile Include="Collections\IPopsicleList.cs" />
@@ -116,10 +124,16 @@
<Compile Include="Descriptors\PackageDescriptor.cs" />
<Compile Include="Descriptors\ServiceDescriptor.cs" />
<Compile Include="DynamicMessage.cs" />
+ <Compile Include="EnumLite.cs" />
<Compile Include="ExtendableBuilder.cs" />
+ <Compile Include="ExtendableBuilderLite.cs" />
<Compile Include="ExtendableMessage.cs" />
- <Compile Include="ExtensionInfo.cs" />
+ <Compile Include="ExtendableMessageLite.cs" />
+ <Compile Include="ExtensionInfo.cs">
+ <SubType>Code</SubType>
+ </Compile>
<Compile Include="ExtensionRegistry.cs" />
+ <Compile Include="ExtensionRegistryLite.cs" />
<Compile Include="FieldAccess\ReflectionUtil.cs" />
<Compile Include="FieldAccess\SingleEnumAccessor.cs" />
<Compile Include="FieldAccess\SingleMessageAccessor.cs" />
@@ -131,12 +145,19 @@
<Compile Include="FieldAccess\RepeatedMessageAccessor.cs" />
<Compile Include="FieldSet.cs" />
<Compile Include="GeneratedBuilder.cs" />
+ <Compile Include="GeneratedBuilderLite.cs" />
+ <Compile Include="GeneratedExtensionLite.cs" />
+ <Compile Include="GeneratedMessageLite.cs" />
<Compile Include="GeneratedRepeatExtension.cs" />
<Compile Include="GeneratedSingleExtension.cs" />
<Compile Include="GeneratedMessage.cs" />
<Compile Include="IBuilder.cs" />
<Compile Include="GeneratedExtensionBase.cs" />
+ <Compile Include="IBuilderLite.cs">
+ <SubType>Code</SubType>
+ </Compile>
<Compile Include="IMessage.cs" />
+ <Compile Include="IMessageLite.cs" />
<Compile Include="InvalidProtocolBufferException.cs" />
<Compile Include="IRpcChannel.cs" />
<Compile Include="IRpcController.cs" />
diff --git a/src/ProtocolBuffers/ProtocolBuffersLite.csproj b/src/ProtocolBuffers/ProtocolBuffersLite.csproj
new file mode 100644
index 00000000..d4413d83
--- /dev/null
+++ b/src/ProtocolBuffers/ProtocolBuffersLite.csproj
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{6969BDCE-D925-43F3-94AC-A531E6DF2591}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Google.ProtocolBuffers</RootNamespace>
+ <AssemblyName>Google.ProtocolBuffersLite</AssemblyName>
+ <TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <SignAssembly>true</SignAssembly>
+ <AssemblyOriginatorKeyFile>Properties\Google.ProtocolBuffers.snk</AssemblyOriginatorKeyFile>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>3.5</OldToolsVersion>
+ <UpgradeBackupLocation />
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>TRACE;DEBUG;LITE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <NoStdLib>true</NoStdLib>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE;LITE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <NoStdLib>true</NoStdLib>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug_Silverlight2|AnyCPU'">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug_Silverlight2\</OutputPath>
+ <DefineConstants>DEBUG;TRACE;SILVERLIGHT2;LITE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <NoStdLib>true</NoStdLib>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release_Silverlight2|AnyCPU'">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release_Silverlight2\</OutputPath>
+ <DefineConstants>TRACE;SILVERLIGHT2;LITE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <NoStdLib>true</NoStdLib>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="mscorlib" />
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="Properties\Google.ProtocolBuffers.snk" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="AbstractBuilderLite.cs" />
+ <Compile Include="AbstractMessageLite.cs" />
+ <Compile Include="Collections\Dictionaries.cs" />
+ <Compile Include="Collections\Enumerables.cs" />
+ <Compile Include="Collections\IPopsicleList.cs" />
+ <Compile Include="Collections\Lists.cs" />
+ <Compile Include="Collections\PopsicleList.cs" />
+ <Compile Include="Collections\ReadOnlyDictionary.cs" />
+ <Compile Include="Descriptors\FieldMappingAttribute.cs" />
+ <Compile Include="Descriptors\FieldType.cs" />
+ <Compile Include="Descriptors\MappedType.cs" />
+ <Compile Include="EnumLite.cs" />
+ <Compile Include="ExtendableBuilderLite.cs" />
+ <Compile Include="ExtendableMessageLite.cs" />
+ <Compile Include="FieldSet.cs" />
+ <Compile Include="GeneratedBuilderLite.cs" />
+ <Compile Include="GeneratedExtensionLite.cs" />
+ <Compile Include="GeneratedMessageLite.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="ByteString.cs" />
+ <Compile Include="CodedInputStream.cs" />
+ <Compile Include="CodedOutputStream.cs" />
+ <Compile Include="ExtensionRegistryLite.cs" />
+ <Compile Include="IBuilderLite.cs" />
+ <Compile Include="IMessageLite.cs">
+ <SubType>Code</SubType>
+ </Compile>
+ <Compile Include="InvalidProtocolBufferException.cs" />
+ <Compile Include="ThrowHelper.cs" />
+ <Compile Include="UninitializedMessageException.cs" />
+ <Compile Include="WireFormat.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" Condition=" '$(Configuration)' != 'Silverlight2' " />
+ <Import Project="$(MSBuildExtensionsPath)\Microsoft\Silverlight\v2.0\Microsoft.Silverlight.CSharp.targets" Condition=" '$(Configuration)' == 'Silverlight2' " />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/src/ProtocolBuffers/SortedList.cs b/src/ProtocolBuffers/SortedList.cs
index e9f4458e..14f14e30 100644
--- a/src/ProtocolBuffers/SortedList.cs
+++ b/src/ProtocolBuffers/SortedList.cs
@@ -50,6 +50,18 @@ namespace Google.ProtocolBuffers
{
private readonly IDictionary<TKey, TValue> wrapped = new Dictionary<TKey, TValue>();
+ public SortedList()
+ {
+ }
+
+ public SortedList(IDictionary<TKey, TValue> dictionary)
+ {
+ foreach (KeyValuePair<TKey, TValue> entry in dictionary)
+ {
+ Add(entry.Key, entry.Value);
+ }
+ }
+
public void Add(TKey key, TValue value)
{
wrapped.Add(key, value);
diff --git a/src/ProtocolBuffers/TextFormat.cs b/src/ProtocolBuffers/TextFormat.cs
index 5f07e693..81b3447c 100644
--- a/src/ProtocolBuffers/TextFormat.cs
+++ b/src/ProtocolBuffers/TextFormat.cs
@@ -170,13 +170,19 @@ namespace Google.ProtocolBuffers {
}
case FieldType.Enum: {
- generator.Print(((EnumValueDescriptor) value).Name);
+ if (value is IEnumLite && !(value is EnumValueDescriptor)) {
+ throw new NotSupportedException("Lite enumerations are not supported.");
+ }
+ generator.Print(((EnumValueDescriptor)value).Name);
break;
}
case FieldType.Message:
case FieldType.Group:
- Print((IMessage) value, generator);
+ if (value is IMessageLite && !(value is IMessage)) {
+ throw new NotSupportedException("Lite messages are not supported.");
+ }
+ Print((IMessage)value, generator);
break;
}
}
@@ -576,7 +582,9 @@ namespace Google.ProtocolBuffers {
if (extension == null) {
subBuilder = builder.CreateBuilderForField(field);
} else {
- subBuilder = extension.DefaultInstance.WeakCreateBuilderForType();
+ subBuilder = extension.DefaultInstance.WeakCreateBuilderForType() as IBuilder;
+ if (subBuilder == null)
+ throw new NotSupportedException("Lite messages are not supported.");
}
while (!tokenizer.TryConsume(endToken)) {
diff --git a/src/ProtocolBuffers/UninitializedMessageException.cs b/src/ProtocolBuffers/UninitializedMessageException.cs
index 2fa5ef1d..d7f58197 100644
--- a/src/ProtocolBuffers/UninitializedMessageException.cs
+++ b/src/ProtocolBuffers/UninitializedMessageException.cs
@@ -36,8 +36,10 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
+#if !LITE
using Google.ProtocolBuffers.Collections;
using Google.ProtocolBuffers.Descriptors;
+#endif
namespace Google.ProtocolBuffers {
/// <summary>
@@ -47,16 +49,10 @@ namespace Google.ProtocolBuffers {
private readonly IList<string> missingFields;
- public UninitializedMessageException(IMessage message)
- : this(FindMissingFields(message)) {
- }
-
private UninitializedMessageException(IList<string> missingFields)
: base(BuildDescription(missingFields)) {
- this.missingFields = Lists.AsReadOnly(missingFields);
+ this.missingFields = new List<string>(missingFields);
}
-
-
/// <summary>
/// Returns a read-only list of human-readable names of
/// required fields missing from this message. Each name
@@ -93,6 +89,19 @@ namespace Google.ProtocolBuffers {
}
/// <summary>
+ /// For Lite exceptions that do not known how to enumerate missing fields
+ /// </summary>
+ public UninitializedMessageException(IMessageLite message)
+ : base(String.Format("Message {0} is missing required fields", message.GetType())) {
+ missingFields = new List<string>();
+ }
+
+#if !LITE
+ public UninitializedMessageException(IMessage message)
+ : this(FindMissingFields(message)) {
+ }
+
+ /// <summary>
/// Returns a list of the full "paths" of missing required
/// fields in the specified message.
/// </summary>
@@ -120,11 +129,19 @@ namespace Google.ProtocolBuffers {
if (field.IsRepeated) {
int i = 0;
foreach (object element in (IEnumerable) value) {
- FindMissingFields((IMessage) element, SubMessagePrefix(prefix, field, i++), results);
+ if (element is IMessage) {
+ FindMissingFields((IMessage)element, SubMessagePrefix(prefix, field, i++), results);
+ } else {
+ results.Add(prefix + field.Name);
+ }
}
} else {
if (message.HasField(field)) {
- FindMissingFields((IMessage) value, SubMessagePrefix(prefix, field, -1), results);
+ if (value is IMessage) {
+ FindMissingFields((IMessage)value, SubMessagePrefix(prefix, field, -1), results);
+ } else {
+ results.Add(prefix + field.Name);
+ }
}
}
}
@@ -148,5 +165,6 @@ namespace Google.ProtocolBuffers {
result.Append('.');
return result.ToString();
}
+#endif
}
}
diff --git a/src/ProtocolBuffers/UnknownField.cs b/src/ProtocolBuffers/UnknownField.cs
index fdc00650..ad1b59b4 100644
--- a/src/ProtocolBuffers/UnknownField.cs
+++ b/src/ProtocolBuffers/UnknownField.cs
@@ -172,7 +172,9 @@ namespace Google.ProtocolBuffers {
output.WriteBytes(fieldNumber, value);
}
foreach (UnknownFieldSet value in groupList) {
+#pragma warning disable 0612
output.WriteUnknownGroup(fieldNumber, value);
+#pragma warning restore 0612
}
}
@@ -195,7 +197,9 @@ namespace Google.ProtocolBuffers {
result += CodedOutputStream.ComputeBytesSize(fieldNumber, value);
}
foreach (UnknownFieldSet value in groupList) {
+#pragma warning disable 0612
result += CodedOutputStream.ComputeUnknownGroupSize(fieldNumber, value);
+#pragma warning restore 0612
}
return result;
}
diff --git a/src/ProtocolBuffers/UnknownFieldSet.cs b/src/ProtocolBuffers/UnknownFieldSet.cs
index 49c1fa32..594ae8bd 100644
--- a/src/ProtocolBuffers/UnknownFieldSet.cs
+++ b/src/ProtocolBuffers/UnknownFieldSet.cs
@@ -51,7 +51,7 @@ namespace Google.ProtocolBuffers {
///
/// Most users will never need to use this class directly.
/// </summary>
- public sealed class UnknownFieldSet {
+ public sealed class UnknownFieldSet : IMessageLite {
private static readonly UnknownFieldSet defaultInstance = new UnknownFieldSet(new Dictionary<int, UnknownField>());
@@ -139,6 +139,14 @@ namespace Google.ProtocolBuffers {
}
/// <summary>
+ /// Converts the set to a string in protocol buffer text format. This
+ /// is just a trivial wrapper around TextFormat.PrintToString.
+ /// </summary>
+ public void PrintTo(TextWriter writer) {
+ TextFormat.Print(this, writer);
+ }
+
+ /// <summary>
/// Serializes the message to a ByteString and returns it. This is
/// just a trivial wrapper around WriteTo(CodedOutputStream).
/// </summary>
@@ -237,16 +245,43 @@ namespace Google.ProtocolBuffers {
return CreateBuilder().MergeFrom(input).Build();
}
+ #region IMessageLite Members
+
+ public bool IsInitialized {
+ get { return fields != null; }
+ }
+
+ public void WriteDelimitedTo(Stream output) {
+ CodedOutputStream codedOutput = CodedOutputStream.CreateInstance(output);
+ codedOutput.WriteRawVarint32((uint) SerializedSize);
+ WriteTo(codedOutput);
+ codedOutput.Flush();
+ }
+
+ public IBuilderLite WeakCreateBuilderForType() {
+ return new Builder();
+ }
+
+ public IBuilderLite WeakToBuilder() {
+ return new Builder(fields);
+ }
+
+ public IMessageLite WeakDefaultInstanceForType {
+ get { return defaultInstance; }
+ }
+
+ #endregion
+
/// <summary>
/// Builder for UnknownFieldSets.
/// </summary>
- public sealed class Builder
+ public sealed class Builder : IBuilderLite
{
/// <summary>
/// Mapping from number to field. Note that by using a SortedList we ensure
/// that the fields will be serialized in ascending order.
/// </summary>
- private IDictionary<int, UnknownField> fields = new SortedList<int, UnknownField>();
+ private IDictionary<int, UnknownField> fields;
// Optimization: We keep around a builder for the last field that was
// modified so that we can efficiently add to it multiple times in a
// row (important when parsing an unknown repeated field).
@@ -254,6 +289,11 @@ namespace Google.ProtocolBuffers {
private UnknownField.Builder lastField;
internal Builder() {
+ fields = new SortedList<int, UnknownField>();
+ }
+
+ internal Builder(IDictionary<int, UnknownField> dictionary) {
+ fields = new SortedList<int, UnknownField>(dictionary);
}
/// <summary>
@@ -356,7 +396,9 @@ namespace Google.ProtocolBuffers {
return true;
case WireFormat.WireType.StartGroup: {
Builder subBuilder = CreateBuilder();
+#pragma warning disable 0612
input.ReadUnknownGroup(number, subBuilder);
+#pragma warning restore 0612
GetFieldBuilder(number).AddGroup(subBuilder.Build());
return true;
}
@@ -469,6 +511,7 @@ namespace Google.ProtocolBuffers {
if (tag == 0) {
break;
}
+
if (!MergeFieldFrom(input, extensionRegistry, builder, tag)) {
// end group tag
break;
@@ -485,7 +528,7 @@ namespace Google.ProtocolBuffers {
/// <param name="builder">Builder to merge field into, if it's a known field</param>
/// <param name="tag">The tag, which should already have been read from the input</param>
/// <returns>true unless the tag is an end-group tag</returns>
- internal bool MergeFieldFrom(CodedInputStream input,
+ internal bool MergeFieldFrom(CodedInputStream input,
ExtensionRegistry extensionRegistry, IBuilder builder, uint tag) {
MessageDescriptor type = builder.DescriptorForType;
@@ -498,7 +541,7 @@ namespace Google.ProtocolBuffers {
int fieldNumber = WireFormat.GetTagFieldNumber(tag);
FieldDescriptor field;
- IMessage defaultFieldInstance = null;
+ IMessageLite defaultFieldInstance = null;
if (type.IsExtensionNumber(fieldNumber)) {
ExtensionInfo extension = extensionRegistry[type, fieldNumber];
@@ -543,14 +586,14 @@ namespace Google.ProtocolBuffers {
switch (field.FieldType) {
case FieldType.Group:
case FieldType.Message: {
- IBuilder subBuilder;
+ IBuilderLite subBuilder;
if (defaultFieldInstance != null) {
subBuilder = defaultFieldInstance.WeakCreateBuilderForType();
} else {
subBuilder = builder.CreateBuilderForField(field);
}
if (!field.IsRepeated) {
- subBuilder.WeakMergeFrom((IMessage)builder[field]);
+ subBuilder.WeakMergeFrom((IMessageLite)builder[field]);
}
if (field.FieldType == FieldType.Group) {
input.ReadGroup(field.FieldNumber, subBuilder, extensionRegistry);
@@ -609,7 +652,7 @@ namespace Google.ProtocolBuffers {
int typeId = 0;
ByteString rawBytes = null; // If we encounter "message" before "typeId"
- IBuilder subBuilder = null;
+ IBuilderLite subBuilder = null;
FieldDescriptor field = null;
while (true) {
@@ -626,7 +669,7 @@ namespace Google.ProtocolBuffers {
if (extension != null) {
field = extension.Descriptor;
subBuilder = extension.DefaultInstance.WeakCreateBuilderForType();
- IMessage originalMessage = (IMessage)builder[field];
+ IMessageLite originalMessage = (IMessageLite)builder[field];
if (originalMessage != null) {
subBuilder.WeakMergeFrom(originalMessage);
}
@@ -672,6 +715,54 @@ namespace Google.ProtocolBuffers {
builder[field] = subBuilder.WeakBuild();
}
}
+
+ #region IBuilderLite Members
+
+ bool IBuilderLite.IsInitialized {
+ get { return fields != null; }
+ }
+
+ IBuilderLite IBuilderLite.WeakClear() {
+ return Clear();
+ }
+
+ IBuilderLite IBuilderLite.WeakMergeFrom(IMessageLite message) {
+ return MergeFrom((UnknownFieldSet)message);
+ }
+
+ IBuilderLite IBuilderLite.WeakMergeFrom(ByteString data) {
+ return MergeFrom(data);
+ }
+
+ IBuilderLite IBuilderLite.WeakMergeFrom(ByteString data, ExtensionRegistry registry) {
+ return MergeFrom(data);
+ }
+
+ IBuilderLite IBuilderLite.WeakMergeFrom(CodedInputStream input) {
+ return MergeFrom(input);
+ }
+
+ IBuilderLite IBuilderLite.WeakMergeFrom(CodedInputStream input, ExtensionRegistry registry) {
+ return MergeFrom(input);
+ }
+
+ IMessageLite IBuilderLite.WeakBuild() {
+ return Build();
+ }
+
+ IMessageLite IBuilderLite.WeakBuildPartial() {
+ return Build();
+ }
+
+ IBuilderLite IBuilderLite.WeakClone() {
+ return Build().WeakToBuilder();
+ }
+
+ IMessageLite IBuilderLite.WeakDefaultInstanceForType {
+ get { return DefaultInstance; }
+ }
+
+ #endregion
}
}
}
diff --git a/src/ProtocolBuffers/WireFormat.cs b/src/ProtocolBuffers/WireFormat.cs
index 22346460..508f1b48 100644
--- a/src/ProtocolBuffers/WireFormat.cs
+++ b/src/ProtocolBuffers/WireFormat.cs
@@ -33,7 +33,9 @@
#endregion
using System;
+#if !LITE
using Google.ProtocolBuffers.Descriptors;
+#endif
namespace Google.ProtocolBuffers {
@@ -115,6 +117,7 @@ namespace Google.ProtocolBuffers {
return (uint) (fieldNumber << TagTypeBits) | (uint) wireType;
}
+#if !LITE
[CLSCompliant(false)]
public static uint MakeTag(FieldDescriptor field) {
return MakeTag(field.FieldNumber, GetWireType(field));
@@ -170,5 +173,6 @@ namespace Google.ProtocolBuffers {
throw new ArgumentOutOfRangeException("No such field type");
}
}
+#endif
}
}