Commit f26f8dce authored by Jon Skeet's avatar Jon Skeet

The great generics revisiting.

parent 9134a21f
......@@ -10,15 +10,13 @@ namespace Google.ProtocolBuffers {
[Test]
public void Clear() {
AbstractMessageWrapper message = (AbstractMessageWrapper)
new AbstractMessageWrapper.Builder(TestAllTypes.CreateBuilder(TestUtil.GetAllSet())).Clear().Build();
AbstractMessageWrapper message = new AbstractMessageWrapper.Builder(TestAllTypes.CreateBuilder(TestUtil.GetAllSet())).Clear().Build();
TestUtil.AssertClear((TestAllTypes) message.WrappedMessage);
}
[Test]
public void Copy() {
AbstractMessageWrapper message = (AbstractMessageWrapper)
new AbstractMessageWrapper.Builder(TestAllTypes.CreateBuilder()).MergeFrom(TestUtil.GetAllSet()).Build();
AbstractMessageWrapper message = new AbstractMessageWrapper.Builder(TestAllTypes.CreateBuilder()).MergeFrom(TestUtil.GetAllSet()).Build();
TestUtil.AssertAllFieldsSet((TestAllTypes) message.WrappedMessage);
}
......@@ -40,7 +38,7 @@ namespace Google.ProtocolBuffers {
[Test]
public void Parsing() {
IBuilder builder = new AbstractMessageWrapper.Builder(TestAllTypes.CreateBuilder());
AbstractMessageWrapper message = (AbstractMessageWrapper) builder.MergeFrom(TestUtil.GetAllSet().ToByteString()).Build();
AbstractMessageWrapper message = (AbstractMessageWrapper) builder.WeakMergeFrom(TestUtil.GetAllSet().ToByteString()).WeakBuild();
TestUtil.AssertAllFieldsSet((TestAllTypes) message.WrappedMessage);
}
......@@ -177,7 +175,7 @@ namespace Google.ProtocolBuffers {
Assert.AreEqual(message, message);
// Object should be equal to a dynamic copy of itself.
DynamicMessage dynamic = (DynamicMessage) ((IBuilder) DynamicMessage.CreateBuilder(message)).Build();
DynamicMessage dynamic = DynamicMessage.CreateBuilder(message).Build();
Assert.AreEqual(message, dynamic);
Assert.AreEqual(dynamic, message);
Assert.AreEqual(dynamic.GetHashCode(), message.GetHashCode());
......@@ -207,7 +205,7 @@ namespace Google.ProtocolBuffers {
/// test that AbstractMessage's implementations work even if the wrapped
/// object does not use them.
/// </summary>
private class AbstractMessageWrapper : AbstractMessage {
private class AbstractMessageWrapper : AbstractMessage<AbstractMessageWrapper, AbstractMessageWrapper.Builder> {
private readonly IMessage wrappedMessage;
public IMessage WrappedMessage {
......@@ -222,8 +220,8 @@ namespace Google.ProtocolBuffers {
get { return wrappedMessage.DescriptorForType; }
}
protected override IMessage DefaultInstanceForTypeImpl {
get { return new AbstractMessageWrapper(wrappedMessage.DefaultInstanceForType); }
public override AbstractMessageWrapper DefaultInstanceForType {
get { return new AbstractMessageWrapper(wrappedMessage.WeakDefaultInstanceForType); }
}
public override IDictionary<FieldDescriptor, object> AllFields {
......@@ -250,17 +248,26 @@ namespace Google.ProtocolBuffers {
get { return wrappedMessage.UnknownFields; }
}
protected override IBuilder CreateBuilderForTypeImpl() {
return new Builder(wrappedMessage.CreateBuilderForType());
public override Builder CreateBuilderForType() {
return new Builder(wrappedMessage.WeakCreateBuilderForType());
}
internal class Builder : AbstractBuilder {
internal class Builder : AbstractBuilder<AbstractMessageWrapper, Builder> {
private readonly IBuilder wrappedBuilder;
protected override Builder ThisBuilder {
get { return this; }
}
internal Builder(IBuilder wrappedBuilder) {
this.wrappedBuilder = wrappedBuilder;
}
public override Builder MergeFrom(AbstractMessageWrapper other) {
wrappedBuilder.WeakMergeFrom(other.wrappedMessage);
return this;
}
public override bool IsInitialized {
get { return wrappedBuilder.IsInitialized; }
}
......@@ -296,29 +303,29 @@ namespace Google.ProtocolBuffers {
set { wrappedBuilder.UnknownFields = value; }
}
protected override IMessage BuildImpl() {
return new AbstractMessageWrapper(wrappedBuilder.Build());
public override AbstractMessageWrapper Build() {
return new AbstractMessageWrapper(wrappedBuilder.WeakBuild());
}
protected override IMessage BuildPartialImpl() {
return new AbstractMessageWrapper(wrappedBuilder.BuildPartial());
public override AbstractMessageWrapper BuildPartial() {
return new AbstractMessageWrapper(wrappedBuilder.WeakBuildPartial());
}
protected override IBuilder CloneImpl() {
return new Builder(wrappedBuilder.Clone());
public override Builder Clone() {
return new Builder(wrappedBuilder.WeakClone());
}
protected override IMessage DefaultInstanceForTypeImpl {
get { return wrappedBuilder.DefaultInstanceForType; }
public override AbstractMessageWrapper DefaultInstanceForType {
get { return new AbstractMessageWrapper(wrappedBuilder.WeakDefaultInstanceForType); }
}
protected override IBuilder ClearFieldImpl(FieldDescriptor field) {
wrappedBuilder.ClearField(field);
public override Builder ClearField(FieldDescriptor field) {
wrappedBuilder.WeakClearField(field);
return this;
}
protected override IBuilder AddRepeatedFieldImpl(FieldDescriptor field, object value) {
wrappedBuilder.AddRepeatedField(field, value);
public override Builder AddRepeatedField(FieldDescriptor field, object value) {
wrappedBuilder.WeakAddRepeatedField(field, value);
return this;
}
......@@ -327,13 +334,13 @@ namespace Google.ProtocolBuffers {
return this;
}
public override IBuilder MergeFrom(IMessage other) {
wrappedBuilder.MergeFrom(other);
public override Builder MergeFrom(IMessage other) {
wrappedBuilder.WeakMergeFrom(other);
return this;
}
protected override IBuilder MergeFromImpl(CodedInputStream input, ExtensionRegistry extensionRegistry) {
wrappedBuilder.MergeFrom(input, extensionRegistry);
public override Builder MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry) {
wrappedBuilder.WeakMergeFrom(input, extensionRegistry);
return this;
}
}
......
......@@ -21,7 +21,7 @@ namespace Google.ProtocolBuffers {
public void DynamicMessageAccessors() {
IBuilder builder = DynamicMessage.CreateBuilder(TestAllTypes.Descriptor);
reflectionTester.SetAllFieldsViaReflection(builder);
IMessage message = builder.Build();
IMessage message = builder.WeakBuild();
reflectionTester.AssertAllFieldsSetViaReflection(message);
}
......@@ -32,7 +32,7 @@ namespace Google.ProtocolBuffers {
// It treats them just like any other fields.
IBuilder builder = DynamicMessage.CreateBuilder(TestAllExtensions.Descriptor);
extensionsReflectionTester.SetAllFieldsViaReflection(builder);
IMessage message = builder.Build();
IMessage message = builder.WeakBuild();
extensionsReflectionTester.AssertAllFieldsSetViaReflection(message);
}
......@@ -41,7 +41,7 @@ namespace Google.ProtocolBuffers {
IBuilder builder = DynamicMessage.CreateBuilder(TestAllTypes.Descriptor);
reflectionTester.SetAllFieldsViaReflection(builder);
reflectionTester.ModifyRepeatedFieldsViaReflection(builder);
IMessage message = builder.Build();
IMessage message = builder.WeakBuild();
reflectionTester.AssertRepeatedFieldsModifiedViaReflection(message);
}
......@@ -57,7 +57,7 @@ namespace Google.ProtocolBuffers {
IBuilder dynamicBuilder = DynamicMessage.CreateBuilder(TestAllTypes.Descriptor);
reflectionTester.SetAllFieldsViaReflection(dynamicBuilder);
IMessage dynamicMessage = dynamicBuilder.Build();
IMessage dynamicMessage = dynamicBuilder.WeakBuild();
Assert.AreEqual(message.SerializedSize, dynamicMessage.SerializedSize);
}
......@@ -66,7 +66,7 @@ namespace Google.ProtocolBuffers {
public void DynamicMessageSerialization() {
IBuilder builder = DynamicMessage.CreateBuilder(TestAllTypes.Descriptor);
reflectionTester.SetAllFieldsViaReflection(builder);
IMessage message = builder.Build();
IMessage message = builder.WeakBuild();
ByteString rawBytes = message.ToByteString();
TestAllTypes message2 = TestAllTypes.ParseFrom(rawBytes);
......
......@@ -153,8 +153,7 @@ namespace Google.ProtocolBuffers {
builder[descriptor.FindDescriptor<FieldDescriptor>("optional_message")] = TestRequiredInitialized;
Assert.IsTrue(builder.IsInitialized);
// TODO(jonskeet): Remove this nastiness by making IBuilder always generic.
((IBuilder) builder).AddRepeatedField(descriptor.FindDescriptor<FieldDescriptor>("repeated_message"), TestRequiredUninitialized);
builder.AddRepeatedField(descriptor.FindDescriptor<FieldDescriptor>("repeated_message"), TestRequiredUninitialized);
Assert.IsFalse(builder.IsInitialized);
builder.SetRepeatedField(descriptor.FindDescriptor<FieldDescriptor>("repeated_message"), 0, TestRequiredInitialized);
......@@ -266,8 +265,7 @@ namespace Google.ProtocolBuffers {
[Test]
public void DynamicBuildPartial() {
// We're mostly testing that no exception is thrown.
// TODO(jonskeet): Fix this ghastly casting mess
DynamicMessage message = (DynamicMessage) ((IBuilder) DynamicMessage.CreateBuilder(TestRequired.Descriptor)).BuildPartial();
DynamicMessage message = DynamicMessage.CreateBuilder(TestRequired.Descriptor).BuildPartial();
Assert.IsFalse(message.Initialized);
}
......
......@@ -95,12 +95,16 @@ namespace Google.ProtocolBuffers.TestProtos {
}
public static Builder CreateBuilder() { return new Builder(); }
public override IBuilder<self::MessageWithNoOuter.Types.NestedMessage> CreateBuilderForType() { return new Builder(); }
public override Builder CreateBuilderForType() { return new Builder(); }
public static Builder CreateBuilder(self::MessageWithNoOuter.Types.NestedMessage prototype) {
return (Builder) new Builder().MergeFrom(prototype);
}
public sealed partial class Builder : pb::GeneratedBuilder<self::MessageWithNoOuter.Types.NestedMessage, Builder> {
protected override Builder ThisBuilder {
get { return this; }
}
// Construct using self::MessageWithNoOuter.Types.NestedMessage.CreateBuilder()
internal Builder() {}
......@@ -110,12 +114,12 @@ namespace Google.ProtocolBuffers.TestProtos {
get { return result; }
}
public override IBuilder<self::MessageWithNoOuter.Types.NestedMessage> Clear() {
public override Builder Clear() {
result = new self::MessageWithNoOuter.Types.NestedMessage();
return this;
}
public override IBuilder<self::MessageWithNoOuter.Types.NestedMessage> Clone() {
public override Builder Clone() {
return new Builder().MergeFrom(result);
}
......@@ -231,12 +235,16 @@ namespace Google.ProtocolBuffers.TestProtos {
}
public static Builder CreateBuilder() { return new Builder(); }
public override IBuilder<self::MessageWithNoOuter> CreateBuilderForType() { return new Builder(); }
public override Builder CreateBuilderForType() { return new Builder(); }
public static Builder CreateBuilder(self::MessageWithNoOuter prototype) {
return (Builder) new Builder().MergeFrom(prototype);
}
public sealed partial class Builder : pb::GeneratedBuilder<self::MessageWithNoOuter, Builder> {
protected override Builder ThisBuilder {
get { return this; }
}
// Construct using self::MessageWithNoOuter.CreateBuilder()
internal Builder() {}
......@@ -246,12 +254,12 @@ namespace Google.ProtocolBuffers.TestProtos {
get { return result; }
}
public override IBuilder<self::MessageWithNoOuter> Clear() {
public override Builder Clear() {
result = new self::MessageWithNoOuter();
return this;
}
public override IBuilder<self::MessageWithNoOuter> Clone() {
public override Builder Clone() {
return new Builder().MergeFrom(result);
}
......
......@@ -59,8 +59,8 @@ namespace Google.ProtocolBuffers.TestProtos {
#endregion
#region Extensions
public static readonly pb::GeneratedExtensionBase<self::TestAllExtensions, int> ExtensionWithOuter =
pb::GeneratedSingleExtension<self::TestAllExtensions, int>.CreateInstance(Descriptor.Extensions[0]);
public static readonly pb::GeneratedExtensionBase<int> ExtensionWithOuter =
pb::GeneratedSingleExtension<int>.CreateInstance(Descriptor.Extensions[0]);
#endregion
#region Static variables
......
......@@ -95,7 +95,7 @@ namespace Google.ProtocolBuffers.TestProtos {
controller,
request,
self::TestAllTypes.DefaultInstance,
pb::RpcUtil.GeneralizeCallback(done, self::TestAllTypes.DefaultInstance));
pb::RpcUtil.GeneralizeCallback<self::TestAllTypes, self::TestAllTypes.Builder>(done, self::TestAllTypes.DefaultInstance));
}
}
}
......
......@@ -174,12 +174,16 @@ namespace Google.ProtocolBuffers.TestProtos {
}
public static Builder CreateBuilder() { return new Builder(); }
public override IBuilder<self::TestEmbedOptimizedForSize> CreateBuilderForType() { return new Builder(); }
public override Builder CreateBuilderForType() { return new Builder(); }
public static Builder CreateBuilder(self::TestEmbedOptimizedForSize prototype) {
return (Builder) new Builder().MergeFrom(prototype);
}
public sealed partial class Builder : pb::GeneratedBuilder<self::TestEmbedOptimizedForSize, Builder> {
protected override Builder ThisBuilder {
get { return this; }
}
// Construct using self::TestEmbedOptimizedForSize.CreateBuilder()
internal Builder() {}
......@@ -189,12 +193,12 @@ namespace Google.ProtocolBuffers.TestProtos {
get { return result; }
}
public override IBuilder<self::TestEmbedOptimizedForSize> Clear() {
public override Builder Clear() {
result = new self::TestEmbedOptimizedForSize();
return this;
}
public override IBuilder<self::TestEmbedOptimizedForSize> Clone() {
public override Builder Clone() {
return new Builder().MergeFrom(result);
}
......@@ -215,11 +219,7 @@ namespace Google.ProtocolBuffers.TestProtos {
return returnMe;
}
protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) {
return MergeFrom(data, extensionRegistry);
}
public override IBuilder MergeFrom(pb::IMessage other) {
public override Builder MergeFrom(pb::IMessage other) {
if (other is self::TestEmbedOptimizedForSize) {
return MergeFrom((self::TestEmbedOptimizedForSize) other);
} else {
......@@ -228,7 +228,7 @@ namespace Google.ProtocolBuffers.TestProtos {
}
}
public override IBuilder<self::TestEmbedOptimizedForSize> MergeFrom(self::TestEmbedOptimizedForSize other) {
public override Builder MergeFrom(self::TestEmbedOptimizedForSize other) {
if (other == self::TestEmbedOptimizedForSize.DefaultInstance) return this;
if (other.HasOptionalMessage) {
MergeOptionalMessage(other.OptionalMessage);
......@@ -243,11 +243,11 @@ namespace Google.ProtocolBuffers.TestProtos {
return this;
}
public override IBuilder<self::TestEmbedOptimizedForSize> MergeFrom(pb::CodedInputStream input) {
public override Builder MergeFrom(pb::CodedInputStream input) {
return MergeFrom(input, pb::ExtensionRegistry.Empty);
}
public override IBuilder<self::TestEmbedOptimizedForSize> MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
pb::UnknownFieldSet.Builder unknownFields =
pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
while (true) {
......
......@@ -150,12 +150,16 @@ namespace Google.ProtocolBuffers.TestProtos {
}
public static Builder CreateBuilder() { return new Builder(); }
public override IBuilder<self::ImportMessage> CreateBuilderForType() { return new Builder(); }
public override Builder CreateBuilderForType() { return new Builder(); }
public static Builder CreateBuilder(self::ImportMessage prototype) {
return (Builder) new Builder().MergeFrom(prototype);
}
public sealed partial class Builder : pb::GeneratedBuilder<self::ImportMessage, Builder> {
protected override Builder ThisBuilder {
get { return this; }
}
// Construct using self::ImportMessage.CreateBuilder()
internal Builder() {}
......@@ -165,12 +169,12 @@ namespace Google.ProtocolBuffers.TestProtos {
get { return result; }
}
public override IBuilder<self::ImportMessage> Clear() {
public override Builder Clear() {
result = new self::ImportMessage();
return this;
}
public override IBuilder<self::ImportMessage> Clone() {
public override Builder Clone() {
return new Builder().MergeFrom(result);
}
......@@ -188,11 +192,7 @@ namespace Google.ProtocolBuffers.TestProtos {
return returnMe;
}
protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) {
return MergeFrom(data, extensionRegistry);
}
public override IBuilder MergeFrom(pb::IMessage other) {
public override Builder MergeFrom(pb::IMessage other) {
if (other is self::ImportMessage) {
return MergeFrom((self::ImportMessage) other);
} else {
......@@ -201,7 +201,7 @@ namespace Google.ProtocolBuffers.TestProtos {
}
}
public override IBuilder<self::ImportMessage> MergeFrom(self::ImportMessage other) {
public override Builder MergeFrom(self::ImportMessage other) {
if (other == self::ImportMessage.DefaultInstance) return this;
if (other.HasD) {
D = other.D;
......@@ -210,11 +210,11 @@ namespace Google.ProtocolBuffers.TestProtos {
return this;
}
public override IBuilder<self::ImportMessage> MergeFrom(pb::CodedInputStream input) {
public override Builder MergeFrom(pb::CodedInputStream input) {
return MergeFrom(input, pb::ExtensionRegistry.Empty);
}
public override IBuilder<self::ImportMessage> MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
pb::UnknownFieldSet.Builder unknownFields =
pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
while (true) {
......
......@@ -77,8 +77,8 @@ namespace Google.ProtocolBuffers.TestProtos {
#region Nested types
public static class Types {
public static readonly pb::GeneratedExtensionBase<self::TestOptimizedForSize, int> TestExtension =
pb::GeneratedSingleExtension<self::TestOptimizedForSize, int>.CreateInstance(Descriptor.Extensions[0]);
public static readonly pb::GeneratedExtensionBase<int> TestExtension =
pb::GeneratedSingleExtension<int>.CreateInstance(Descriptor.Extensions[0]);
}
#endregion
......@@ -137,12 +137,16 @@ namespace Google.ProtocolBuffers.TestProtos {
}
public static Builder CreateBuilder() { return new Builder(); }
public override IBuilder<self::TestOptimizedForSize> CreateBuilderForType() { return new Builder(); }
public override Builder CreateBuilderForType() { return new Builder(); }
public static Builder CreateBuilder(self::TestOptimizedForSize prototype) {
return (Builder) new Builder().MergeFrom(prototype);
}
public sealed partial class Builder : pb::ExtendableBuilder<self::TestOptimizedForSize, self::TestOptimizedForSize.Builder> {
protected override Builder ThisBuilder {
get { return this; }
}
// Construct using self::TestOptimizedForSize.CreateBuilder()
internal Builder() {}
......@@ -152,12 +156,12 @@ namespace Google.ProtocolBuffers.TestProtos {
get { return result; }
}
public override IBuilder<self::TestOptimizedForSize> Clear() {
public override Builder Clear() {
result = new self::TestOptimizedForSize();
return this;
}
public override IBuilder<self::TestOptimizedForSize> Clone() {
public override Builder Clone() {
return new Builder().MergeFrom(result);
}
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
......@@ -23,7 +23,9 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// Implementation of the non-generic IMessage interface as far as possible.
/// </summary>
public abstract class AbstractMessage : IMessage {
public abstract class AbstractMessage<TMessage, TBuilder> : IMessage<TMessage, TBuilder>
where TMessage : AbstractMessage<TMessage, TBuilder>
where TBuilder : AbstractBuilder<TMessage, TBuilder> {
// TODO(jonskeet): Cleaner to use a Nullable<int>?
/// <summary>
/// The serialized size if it's already been computed, or -1
......@@ -39,21 +41,17 @@ 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();
#endregion
#region New abstract methods to be overridden by implementations, allow explicit interface implementation
protected abstract IMessage DefaultInstanceForTypeImpl { get; }
protected abstract IBuilder CreateBuilderForTypeImpl();
#endregion
#region Methods simply proxying to the "Impl" methods, explicitly implementing IMessage
IMessage IMessage.DefaultInstanceForType {
get { return DefaultInstanceForTypeImpl; }
public IBuilder WeakCreateBuilderForType() {
return CreateBuilderForType();
}
IBuilder IMessage.CreateBuilderForType() {
return CreateBuilderForTypeImpl();
public IMessage WeakDefaultInstanceForType {
get { return DefaultInstanceForType; }
}
#endregion
public virtual bool IsInitialized {
get {
......@@ -71,7 +69,7 @@ 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 (IMessage element in (IEnumerable) entry.Value) {
if (!element.IsInitialized) {
return false;
}
......@@ -124,7 +122,7 @@ namespace Google.ProtocolBuffers {
foreach (KeyValuePair<FieldDescriptor, object> entry in AllFields) {
FieldDescriptor field = entry.Key;
if (field.IsRepeated) {
foreach (object element in (IEnumerable)entry.Value) {
foreach (object element in (IEnumerable) entry.Value) {
size += CodedOutputStream.ComputeFieldSize(field.FieldType, field.FieldNumber, element);
}
} else {
......
......@@ -224,7 +224,7 @@ namespace Google.ProtocolBuffers {
throw InvalidProtocolBufferException.RecursionLimitExceeded();
}
++recursionDepth;
builder.MergeFrom(this, extensionRegistry);
builder.WeakMergeFrom(this, extensionRegistry);
CheckLastTagWas(WireFormat.MakeTag(fieldNumber, WireFormat.WireType.EndGroup));
--recursionDepth;
}
......@@ -253,7 +253,7 @@ namespace Google.ProtocolBuffers {
}
int oldLimit = PushLimit(length);
++recursionDepth;
builder.MergeFrom(this, extensionRegistry);
builder.WeakMergeFrom(this, extensionRegistry);
CheckLastTagWas(0);
--recursionDepth;
PopLimit(oldLimit);
......
This diff is collapsed.
......@@ -13,57 +13,55 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// Checks if a singular extension is present
/// </summary>
public bool HasExtension<TExtension>(GeneratedExtensionBase<TMessage, TExtension> extension) {
public bool HasExtension<TExtension>(GeneratedExtensionBase<TExtension> extension) {
return MessageBeingBuilt.HasExtension(extension);
}
/// <summary>
/// Returns the number of elements in a repeated extension.
/// </summary>
public int GetExtensionCount<TExtension>(GeneratedExtensionBase<TMessage, IList<TExtension>> extension) {
public int GetExtensionCount<TExtension>(GeneratedExtensionBase<IList<TExtension>> extension) {
return MessageBeingBuilt.GetExtensionCount(extension);
}
/// <summary>
/// Returns the value of an extension.
/// </summary>
public TExtension GetExtension<TExtension>(GeneratedExtensionBase<TMessage, TExtension> extension) {
public TExtension GetExtension<TExtension>(GeneratedExtensionBase<TExtension> extension) {
return MessageBeingBuilt.GetExtension(extension);
}
/// <summary>
/// Returns one element of a repeated extension.
/// </summary>
public TExtension GetExtension<TExtension>(GeneratedExtensionBase<TMessage, IList<TExtension>> extension, int index) {
public TExtension GetExtension<TExtension>(GeneratedExtensionBase<IList<TExtension>> extension, int index) {
return MessageBeingBuilt.GetExtension(extension, index);
}
/// <summary>
/// Sets the value of an extension.
/// </summary>
public ExtendableBuilder<TMessage, TBuilder> SetExtension<TExtension>(GeneratedExtensionBase<TMessage, TExtension> extension, TExtension value) {
public TBuilder SetExtension<TExtension>(GeneratedExtensionBase<TExtension> extension, TExtension value) {
ExtendableMessage<TMessage, TBuilder> message = MessageBeingBuilt;
message.VerifyExtensionContainingType(extension);
message.Extensions[extension.Descriptor] = extension.ToReflectionType(value);
return this;
return ThisBuilder;
}
/// <summary>
/// Sets the value of one element of a repeated extension.
/// </summary>
public ExtendableBuilder<TMessage, TBuilder> SetExtension<TExtension>(
GeneratedExtensionBase<TMessage, IList<TExtension>> extension, int index, TExtension value) {
public TBuilder SetExtension<TExtension>(GeneratedExtensionBase<IList<TExtension>> extension, int index, TExtension value) {
ExtendableMessage<TMessage, TBuilder> message = MessageBeingBuilt;
message.VerifyExtensionContainingType(extension);
message.Extensions[extension.Descriptor, index] = extension.SingularToReflectionType(value);
return this;
return ThisBuilder;
}
/// <summary>
/// Appends a value to a repeated extension.
/// </summary>
public ExtendableBuilder<TMessage, TBuilder> AddExtension<TExtension>(
GeneratedExtensionBase<TMessage, IList<TExtension>> extension, TExtension value) {
public ExtendableBuilder<TMessage, 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));
......@@ -73,8 +71,7 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// Clears an extension.
/// </summary>
public ExtendableBuilder<TMessage, TBuilder> ClearExtension<TExtension>(
GeneratedExtensionBase<TMessage, TExtension> extension) {
public ExtendableBuilder<TMessage, TBuilder> ClearExtension<TExtension>(GeneratedExtensionBase<TExtension> extension) {
ExtendableMessage<TMessage, TBuilder> message = MessageBeingBuilt;
message.VerifyExtensionContainingType(extension);
message.Extensions.ClearField(extension.Descriptor);
......@@ -121,23 +118,23 @@ namespace Google.ProtocolBuffers {
}
}
public override IBuilder<TMessage> ClearField(FieldDescriptor field) {
public override TBuilder ClearField(FieldDescriptor field) {
if (field.IsExtension) {
ExtendableMessage<TMessage, TBuilder> message = MessageBeingBuilt;
message.VerifyContainingType(field);
message.Extensions.ClearField(field);
return this;
return ThisBuilder;
} else {
return base.ClearField(field);
}
}
public override IBuilder<TMessage> AddRepeatedField(FieldDescriptor field, object value) {
public override TBuilder AddRepeatedField(FieldDescriptor field, object value) {
if (field.IsExtension) {
ExtendableMessage<TMessage, TBuilder> message = MessageBeingBuilt;
message.VerifyContainingType(field);
message.Extensions.AddRepeatedField(field, value);
return this;
return ThisBuilder;
} else {
return base.AddRepeatedField(field, value);
}
......
......@@ -5,9 +5,9 @@ using Google.ProtocolBuffers.Descriptors;
using Google.ProtocolBuffers.Collections;
namespace Google.ProtocolBuffers {
public abstract class ExtendableMessage<TMessage,TBuilder> : GeneratedMessage<TMessage,TBuilder>
public abstract class ExtendableMessage<TMessage, TBuilder> : GeneratedMessage<TMessage, TBuilder>
where TMessage : GeneratedMessage<TMessage, TBuilder>
where TBuilder : IBuilder<TMessage> {
where TBuilder : GeneratedBuilder<TMessage, TBuilder> {
protected ExtendableMessage() {}
private readonly FieldSet extensions = FieldSet.CreateFieldSet();
......@@ -22,21 +22,21 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// Checks if a singular extension is present.
/// </summary>
public bool HasExtension<TExtension>(GeneratedExtensionBase<TMessage, TExtension> extension) {
public bool HasExtension<TExtension>(GeneratedExtensionBase<TExtension> extension) {
return extensions.HasField(extension.Descriptor);
}
/// <summary>
/// Returns the number of elements in a repeated extension.
/// </summary>
public int GetExtensionCount<TExtension>(GeneratedExtensionBase<TMessage, IList<TExtension>> extension) {
public int GetExtensionCount<TExtension>(GeneratedExtensionBase<IList<TExtension>> extension) {
return extensions.GetRepeatedFieldCount(extension.Descriptor);
}
/// <summary>
/// Returns the value of an extension.
/// </summary>
public TExtension GetExtension<TExtension>(GeneratedExtensionBase<TMessage, TExtension> extension) {
public TExtension GetExtension<TExtension>(GeneratedExtensionBase<TExtension> extension) {
object value = extensions[extension.Descriptor];
if (value == null) {
return (TExtension) extension.MessageDefaultInstance;
......@@ -48,7 +48,7 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// Returns one element of a repeated extension.
/// </summary>
public TExtension GetExtension<TExtension>(GeneratedExtensionBase<TMessage, IList<TExtension>> extension, int index) {
public TExtension GetExtension<TExtension>(GeneratedExtensionBase<IList<TExtension>> extension, int index) {
return (TExtension) extension.SingularFromReflectionType(extensions[extension.Descriptor, index]);
}
......@@ -169,7 +169,7 @@ namespace Google.ProtocolBuffers {
get { return extensions.SerializedSize; }
}
internal void VerifyExtensionContainingType<TExtension>(GeneratedExtensionBase<TMessage, TExtension> extension) {
internal void VerifyExtensionContainingType<TExtension>(GeneratedExtensionBase<TExtension> extension) {
if (extension.Descriptor.ContainingType != DescriptorForType) {
// This can only happen if someone uses unchecked operations.
throw new ArgumentException("Extension is for type \"" + extension.Descriptor.ContainingType.FullName
......
......@@ -88,8 +88,7 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// Add an extension from a generated file to the registry.
/// </summary>
public void Add<TContainer, TExtension> (GeneratedExtensionBase<TContainer, TExtension> extension)
where TContainer : IMessage<TContainer> {
public void Add<TExtension> (GeneratedExtensionBase<TExtension> extension) {
if (extension.Descriptor.MappedType == MappedType.Message) {
Add(new ExtensionInfo(extension.Descriptor, extension.MessageDefaultInstance));
} else {
......
......@@ -40,7 +40,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;
return CreateBuilder().MergeFrom(message).Build();
return CreateBuilder().WeakMergeFrom(message).WeakBuild();
}
public override void SetRepeated(IBuilder builder, int index, object value) {
......
......@@ -38,7 +38,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;
return CreateBuilder().MergeFrom(message).Build();
return CreateBuilder().WeakMergeFrom(message).WeakBuild();
}
public override void SetValue(IBuilder builder, object value) {
......
......@@ -154,19 +154,19 @@ namespace Google.ProtocolBuffers {
case FieldType.Message: {
IBuilder subBuilder;
if (defaultFieldInstance != null) {
subBuilder = defaultFieldInstance.CreateBuilderForType();
subBuilder = defaultFieldInstance.WeakCreateBuilderForType();
} else {
subBuilder = builder.CreateBuilderForField(field);
}
if (!field.IsRepeated) {
subBuilder.MergeFrom((IMessage) builder[field]);
subBuilder.WeakMergeFrom((IMessage) builder[field]);
}
if (field.FieldType == FieldType.Group) {
input.ReadGroup(field.FieldNumber, subBuilder, extensionRegistry);
} else {
input.ReadMessage(subBuilder, extensionRegistry);
}
value = subBuilder.Build();
value = subBuilder.WeakBuild();
break;
}
case FieldType.Enum: {
......@@ -185,7 +185,7 @@ namespace Google.ProtocolBuffers {
break;
}
if (field.IsRepeated) {
builder.AddRepeatedField(field, value);
builder.WeakAddRepeatedField(field, value);
} else {
builder[field] = value;
}
......@@ -236,16 +236,16 @@ namespace Google.ProtocolBuffers {
ExtensionInfo extension = extensionRegistry[type, typeId];
if (extension != null) {
field = extension.Descriptor;
subBuilder = extension.DefaultInstance.CreateBuilderForType();
subBuilder = extension.DefaultInstance.WeakCreateBuilderForType();
IMessage originalMessage = (IMessage) builder[field];
if (originalMessage != null) {
subBuilder.MergeFrom(originalMessage);
subBuilder.WeakMergeFrom(originalMessage);
}
if (rawBytes != null) {
// We already encountered the message. Parse it now.
// TODO(jonskeet): Check this is okay. It's subtly different from the Java, as it doesn't create an input stream from rawBytes.
// In fact, why don't we just call MergeFrom(rawBytes)? And what about the extension registry?
subBuilder.MergeFrom(rawBytes.CreateCodedInput());
subBuilder.WeakMergeFrom(rawBytes.CreateCodedInput());
rawBytes = null;
}
} else {
......@@ -286,7 +286,7 @@ namespace Google.ProtocolBuffers {
input.CheckLastTagWas(WireFormat.MessageSetTag.ItemEnd);
if (subBuilder != null) {
builder[field] = subBuilder.Build();
builder[field] = subBuilder.WeakBuild();
}
}
......@@ -381,7 +381,7 @@ namespace Google.ProtocolBuffers {
}
/// <summary>
/// See <see cref="IBuilder.AddRepeatedField" />
/// See <see cref="IBuilder{TMessage, TBuilder}.AddRepeatedField" />
/// </summary>
internal void AddRepeatedField(FieldDescriptor field, object value) {
if (!field.IsRepeated) {
......@@ -449,7 +449,7 @@ namespace Google.ProtocolBuffers {
}
/// <summary>
/// See <see cref="IBuilder.ClearField" />
/// See <see cref="IBuilder{TMessage, TBuilder}.ClearField" />
/// </summary>
public void ClearField(FieldDescriptor field) {
fields.Remove(field);
......@@ -495,10 +495,10 @@ namespace Google.ProtocolBuffers {
}
} else if (field.MappedType == MappedType.Message && existingValue != null) {
IMessage existingMessage = (IMessage)existingValue;
IMessage merged = existingMessage.CreateBuilderForType()
.MergeFrom(existingMessage)
.MergeFrom((IMessage)entry.Value)
.Build();
IMessage merged = existingMessage.WeakCreateBuilderForType()
.WeakMergeFrom(existingMessage)
.WeakMergeFrom((IMessage) entry.Value)
.WeakBuild();
this[field] = merged;
} else {
this[field] = entry.Value;
......
......@@ -13,9 +13,9 @@ namespace Google.ProtocolBuffers {
/// most of the IBuilder interface using reflection. Users can ignore this class
/// as an implementation detail.
/// </summary>
public abstract class GeneratedBuilder<TMessage, TBuilder> : AbstractBuilder, IBuilder<TMessage>
public abstract class GeneratedBuilder<TMessage, TBuilder> : AbstractBuilder<TMessage, TBuilder>
where TMessage : GeneratedMessage <TMessage, TBuilder>
where TBuilder : GeneratedBuilder<TMessage, TBuilder>, IBuilder<TMessage> {
where TBuilder : GeneratedBuilder<TMessage, TBuilder> {
/// <summary>
/// Returns the message being built at the moment.
......@@ -43,7 +43,7 @@ namespace Google.ProtocolBuffers {
: MessageBeingBuilt[field];
}
set {
InternalFieldAccessors[field].SetValue(this, value);
InternalFieldAccessors[field].SetValue(ThisBuilder, value);
}
}
......@@ -87,40 +87,16 @@ namespace Google.ProtocolBuffers {
return MessageBeingBuilt.HasField(field);
}
protected override IMessage BuildImpl() {
return Build();
}
protected override IMessage BuildPartialImpl() {
return BuildPartial();
}
protected override IBuilder CloneImpl() {
return Clone();
}
protected override IMessage DefaultInstanceForTypeImpl {
get { return DefaultInstanceForType; }
}
public override IBuilder CreateBuilderForField(FieldDescriptor field) {
return InternalFieldAccessors[field].CreateBuilder();
}
protected override IBuilder ClearFieldImpl(FieldDescriptor field) {
return ClearField(field);
}
protected override IBuilder AddRepeatedFieldImpl(FieldDescriptor field, object value) {
return AddRepeatedField(field, value);
}
public virtual IBuilder<TMessage> ClearField(FieldDescriptor field) {
public override TBuilder ClearField(FieldDescriptor field) {
InternalFieldAccessors[field].Clear(this);
return this;
return ThisBuilder;
}
public virtual IBuilder<TMessage> MergeFrom(TMessage other) {
public override TBuilder MergeFrom(TMessage other) {
if (other.DescriptorForType != InternalFieldAccessors.Descriptor) {
throw new ArgumentException("Message type mismatch");
}
......@@ -135,77 +111,31 @@ namespace Google.ProtocolBuffers {
} else if (field.MappedType == MappedType.Message && HasField(field)) {
// Merge singular embedded messages
IMessage oldValue = (IMessage)this[field];
this[field] = oldValue.CreateBuilderForType()
.MergeFrom(oldValue)
.MergeFrom((IMessage)entry.Value)
.BuildPartial();
this[field] = oldValue.WeakCreateBuilderForType()
.WeakMergeFrom(oldValue)
.WeakMergeFrom((IMessage)entry.Value)
.WeakBuildPartial();
} else {
// Just overwrite
this[field] = entry.Value;
}
}
return this;
return ThisBuilder;
}
public virtual IBuilder<TMessage> MergeUnknownFields(UnknownFieldSet unknownFields) {
public override TBuilder MergeUnknownFields(UnknownFieldSet unknownFields) {
TMessage result = MessageBeingBuilt;
result.SetUnknownFields(UnknownFieldSet.CreateBuilder(result.UnknownFields)
.MergeFrom(unknownFields)
.Build());
return this;
return ThisBuilder;
}
public virtual IBuilder<TMessage> AddRepeatedField(FieldDescriptor field, object value) {
public override TBuilder AddRepeatedField(FieldDescriptor field, object value) {
InternalFieldAccessors[field].AddRepeated(this, value);
return this;
}
public IBuilder<TMessage> MergeFrom(ByteString data) {
((IBuilder) this).MergeFrom(data);
return this;
}
public IBuilder<TMessage> MergeFrom(ByteString data, ExtensionRegistry extensionRegistry) {
((IBuilder) this).MergeFrom(data, extensionRegistry);
return this;
}
public IBuilder<TMessage> MergeFrom(byte[] data) {
((IBuilder) this).MergeFrom(data);
return this;
}
public IBuilder<TMessage> MergeFrom(byte[] data, ExtensionRegistry extensionRegistry) {
((IBuilder) this).MergeFrom(data, extensionRegistry);
return this;
}
public IBuilder<TMessage> MergeFrom(Stream input) {
((IBuilder) this).MergeFrom(input);
return this;
}
public IBuilder<TMessage> MergeFrom(Stream input, ExtensionRegistry extensionRegistry) {
((IBuilder) this).MergeFrom(input, extensionRegistry);
return this;
return ThisBuilder;
}
/// <summary>
/// Overridden when optimized for speed.
/// </summary>
public virtual IBuilder<TMessage> MergeFrom(CodedInputStream input) {
((IBuilder)this).MergeFrom(input);
return this;
}
/// <summary>
/// Overridden when optimized for speed.
/// </summary>
public virtual IBuilder<TMessage> MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry) {
((IBuilder)this).MergeFrom(input, extensionRegistry);
return this;
}
/// <summary>
/// Like Build(), but will wrap UninitializedMessageException in
/// InvalidProtocolBufferException.
......@@ -219,10 +149,10 @@ namespace Google.ProtocolBuffers {
}
/// <summary>
/// Implementation of <see cref="IBuilder{T}.Build" />.
/// Implementation of <see cref="IBuilder{TMessage, TBuilder}.Build" />.
/// TODO(jonskeet): This used to be generated for each class. Find out why.
/// </summary>
public TMessage Build() {
public override TMessage Build() {
if (!IsInitialized) {
throw new UninitializedMessageException(MessageBeingBuilt);
}
......@@ -233,13 +163,5 @@ namespace Google.ProtocolBuffers {
get { return MessageBeingBuilt.UnknownFields; }
set { MessageBeingBuilt.SetUnknownFields(value); }
}
public abstract TMessage BuildPartial();
public abstract IBuilder<TMessage> Clone();
public abstract new IBuilder<TMessage> Clear();
public abstract TMessage DefaultInstanceForType { get; }
public abstract class ExtendableBuilder : GeneratedBuilder<TMessage, TBuilder> {
}
}
}
......@@ -29,7 +29,7 @@ namespace Google.ProtocolBuffers {
/// The interface implemented by both GeneratedException and GeneratedRepeatException,
/// to make it easier to cope with repeats separately.
/// </remarks>
public abstract class GeneratedExtensionBase<TContainer, TExtension> {
public abstract class GeneratedExtensionBase<TExtension> {
private readonly FieldDescriptor descriptor;
private readonly IMessage messageDefaultInstance;
......@@ -73,8 +73,8 @@ namespace Google.ProtocolBuffers {
// 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.CreateBuilderForType()
.MergeFrom((IMessage)value).Build();
return MessageDefaultInstance.WeakCreateBuilderForType()
.WeakMergeFrom((IMessage)value).WeakBuild();
}
case MappedType.Enum:
// Just return a boxed int - that can be unboxed to the enum
......
......@@ -13,9 +13,9 @@ namespace Google.ProtocolBuffers {
/// most of the IMessage interface using reflection. Users
/// can ignore this class as an implementation detail.
/// </summary>
public abstract class GeneratedMessage<TMessage, TBuilder> : AbstractMessage, IMessage<TMessage>
public abstract class GeneratedMessage<TMessage, TBuilder> : AbstractMessage<TMessage, TBuilder>
where TMessage : GeneratedMessage<TMessage, TBuilder>
where TBuilder : IBuilder<TMessage> {
where TBuilder : GeneratedBuilder<TMessage, TBuilder> {
private UnknownFieldSet unknownFields = UnknownFieldSet.DefaultInstance;
......@@ -29,18 +29,6 @@ namespace Google.ProtocolBuffers {
get { return InternalFieldAccessors.Descriptor; }
}
protected override IMessage DefaultInstanceForTypeImpl {
get { return DefaultInstanceForType; }
}
protected override IBuilder CreateBuilderForTypeImpl() {
return CreateBuilderForType();
}
public abstract TMessage DefaultInstanceForType { get; }
public abstract IBuilder<TMessage> CreateBuilderForType();
internal IDictionary<FieldDescriptor, Object> GetMutableFieldMap() {
// Use a SortedList so we'll end up serializing fields in order
......
......@@ -7,15 +7,15 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// Class used to represent repeat extensions in generated classes.
/// </summary>
public class GeneratedRepeatExtension<TContainer, TExtensionElement> : GeneratedExtensionBase<TContainer, IList<TExtensionElement>> {
public class GeneratedRepeatExtension<TExtensionElement> : GeneratedExtensionBase<IList<TExtensionElement>> {
private GeneratedRepeatExtension(FieldDescriptor field) : base(field, typeof(TExtensionElement)) {
}
public static GeneratedExtensionBase<TContainer, IList<TExtensionElement>> CreateInstance(FieldDescriptor descriptor) {
public static GeneratedExtensionBase<IList<TExtensionElement>> CreateInstance(FieldDescriptor descriptor) {
if (!descriptor.IsRepeated) {
throw new ArgumentException("Must call GeneratedRepeatExtension.CreateInstance() for repeated types.");
}
return new GeneratedRepeatExtension<TContainer, TExtensionElement>(descriptor);
return new GeneratedRepeatExtension<TExtensionElement>(descriptor);
}
/// <summary>
......
......@@ -6,17 +6,15 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// Generated extension for a singular field.
/// </remarks>
public class GeneratedSingleExtension<TContainer, TExtension> : GeneratedExtensionBase<TContainer, TExtension>
where TContainer : IMessage<TContainer> {
public class GeneratedSingleExtension<TExtension> : GeneratedExtensionBase<TExtension> {
internal GeneratedSingleExtension(FieldDescriptor descriptor) : base(descriptor, typeof(TExtension)) {
}
public static GeneratedSingleExtension<TContainer, TExtension> CreateInstance(FieldDescriptor descriptor) {
public static GeneratedSingleExtension<TExtension> CreateInstance(FieldDescriptor descriptor) {
if (descriptor.IsRepeated) {
throw new ArgumentException("Must call GeneratedRepeateExtension.CreateInstance() for repeated types.");
}
return new GeneratedSingleExtension<TContainer, TExtension>(descriptor);
return new GeneratedSingleExtension<TExtension>(descriptor);
}
public override object FromReflectionType(object value) {
......
This diff is collapsed.
......@@ -21,11 +21,8 @@ using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers {
/// <summary>
/// Non-generic interface implemented by all Protocol Buffers messages.
/// Some members are repeated in the generic interface but with a
/// type-specific signature. Type-safe implementations
/// are encouraged to implement these non-generic members explicitly,
/// and the generic members implicitly.
/// Non-generic interface used for all parts of the API which don't require
/// any type knowledge.
/// </summary>
public interface IMessage {
/// <summary>
......@@ -152,27 +149,17 @@ namespace Google.ProtocolBuffers {
void WriteTo(Stream output);
#endregion
#region Weakly typed members
/// <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.
/// Creates a builder for the type, but in a weakly typed manner. This
/// is typically implemented by strongly typed builders by just returning
/// the result of CreateBuilderForType.
/// </summary>
IMessage DefaultInstanceForType { get; }
IBuilder WeakCreateBuilderForType();
/// <summary>
/// Constructs a new builder for a message of the same type as this message.
/// </summary>
IBuilder CreateBuilderForType();
#endregion
IMessage WeakDefaultInstanceForType { get; }
}
/// <summary>
/// Type-safe interface for all generated messages to implement.
/// </summary>
public interface IMessage<T> : IMessage where T : IMessage<T> {
public interface IMessage<TMessage> : IMessage {
/// <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
......@@ -180,13 +167,20 @@ 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>
new T DefaultInstanceForType { get; }
TMessage DefaultInstanceForType { get; }
}
/// <summary>
/// Type-safe interface for all generated messages to implement.
/// </summary>
public interface IMessage<TMessage, TBuilder> : IMessage<TMessage>
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>
new IBuilder<T> CreateBuilderForType();
TBuilder CreateBuilderForType();
#endregion
}
}
......@@ -67,13 +67,13 @@ namespace Google.ProtocolBuffers {
internal static InvalidProtocolBufferException RecursionLimitExceeded() {
return new InvalidProtocolBufferException(
"Protocol message had too many levels of nesting. May be malicious. " +
"Use CodedInputStream.setRecursionLimit() to increase the depth limit.");
"Use CodedInputStream.SetRecursionLimit() to increase the depth limit.");
}
internal static InvalidProtocolBufferException SizeLimitExceeded() {
return new InvalidProtocolBufferException(
"Protocol message was too large. May be malicious. " +
"Use CodedInputStream.setSizeLimit() to increase the size limit.");
"Use CodedInputStream.SetSizeLimit() to increase the size limit.");
}
}
}
......@@ -21,12 +21,13 @@ namespace Google.ProtocolBuffers {
/// callback is given a message with a different descriptor, an
/// exception will be thrown.
/// </summary>
public static Action<IMessage> GeneralizeCallback<T>(Action<T> action, T defaultInstance)
where T : class, IMessage<T> {
public static Action<IMessage> GeneralizeCallback<TMessage, TBuilder>(Action<TMessage> action, TMessage defaultInstance)
where TMessage : class, IMessage<TMessage, TBuilder>
where TBuilder : IBuilder<TMessage, TBuilder> {
return message => {
T castMessage = message as T;
TMessage castMessage = message as TMessage;
if (castMessage == null) {
castMessage = (T) defaultInstance.CreateBuilderForType().MergeFrom(message).Build();
castMessage = defaultInstance.CreateBuilderForType().MergeFrom(message).Build();
}
action(castMessage);
};
......
......@@ -44,6 +44,7 @@ namespace Google.ProtocolBuffers {
}
private static void Print(IMessage message, TextGenerator generator) {
// TODO(jonskeet): Check why descriptor is never used.
MessageDescriptor descriptor = message.DescriptorForType;
foreach (KeyValuePair<FieldDescriptor, object> entry in message.AllFields) {
PrintField(entry.Key, entry.Value, generator);
......
......@@ -57,12 +57,12 @@ void ExtensionGenerator::Generate(io::Printer* printer) {
if (descriptor_->is_repeated()) {
printer->Print(vars,
"public static readonly\r\n"
" pb::GeneratedExtensionBase<$containing_type$, scg::IList<$type$>> $name$ =\r\n"
" pb::GeneratedRepeatExtension<$containing_type$, $type$>.CreateInstance(Descriptor.Extensions[$index$]);\r\n");
" pb::GeneratedExtensionBase<scg::IList<$type$>> $name$ =\r\n"
" pb::GeneratedRepeatExtension<$type$>.CreateInstance(Descriptor.Extensions[$index$]);\r\n");
} else {
printer->Print(vars,
"public static readonly pb::GeneratedExtensionBase<$containing_type$, $type$> $name$ =\r\n"
" pb::GeneratedSingleExtension<$containing_type$, $type$>.CreateInstance(Descriptor.Extensions[$index$]);\r\n");
"public static readonly pb::GeneratedExtensionBase<$type$> $name$ =\r\n"
" pb::GeneratedSingleExtension<$type$>.CreateInstance(Descriptor.Extensions[$index$]);\r\n");
}
}
......
......@@ -423,7 +423,7 @@ void MessageGenerator::GenerateSerializeOneExtensionRange(
void MessageGenerator::GenerateBuilder(io::Printer* printer) {
printer->Print(
"public static Builder CreateBuilder() { return new Builder(); }\r\n"
"public override IBuilder<$classname$> CreateBuilderForType() { return new Builder(); }\r\n"
"public override Builder CreateBuilderForType() { return new Builder(); }\r\n"
"public static Builder CreateBuilder($classname$ prototype) {\r\n"
" return (Builder) new Builder().MergeFrom(prototype);\r\n"
"}\r\n"
......@@ -441,8 +441,14 @@ void MessageGenerator::GenerateBuilder(io::Printer* printer) {
"classname", ClassName(descriptor_),
"access", ClassAccessLevel(descriptor_->file()));
}
printer->Indent();
printer->Print(
"protected override Builder ThisBuilder {\r\n"
" get { return this; }\r\n"
"}\r\n\r\n");
GenerateCommonBuilderMethods(printer);
if (descriptor_->file()->options().optimize_for() == FileOptions::SPEED) {
......@@ -475,12 +481,12 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
" get { return result; }\r\n"
"}\r\n"
"\r\n"
"public override IBuilder<$classname$> Clear() {\r\n"
"public override Builder Clear() {\r\n"
" result = new $classname$();\r\n"
" return this;\r\n"
"}\r\n"
"\r\n"
"public override IBuilder<$classname$> Clone() {\r\n"
"public override Builder Clone() {\r\n"
" return new Builder().MergeFrom(result);\r\n"
"}\r\n"
"\r\n"
......@@ -516,14 +522,14 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
// -----------------------------------------------------------------
//TODO(jonskeet): Work out what this is really for...
if (descriptor_->file()->options().optimize_for() == FileOptions::SPEED) {
printer->Print(
"protected override IBuilder MergeFromImpl(CodedInputStream data, ExtensionRegistry extensionRegistry) {\r\n"
/*
"protected override Builder MergeFrom(CodedInputStream data, ExtensionRegistry extensionRegistry) {\r\n"
" return MergeFrom(data, extensionRegistry);\r\n"
"}\r\n"
"\r\n"
"public override IBuilder MergeFrom(pb::IMessage other) {\r\n"
"\r\n"*/
"public override Builder MergeFrom(pb::IMessage other) {\r\n"
" if (other is $classname$) {\r\n"
" return MergeFrom(($classname$) other);\r\n"
" } else {\r\n"
......@@ -532,7 +538,7 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
" }\r\n"
"}\r\n"
"\r\n"
"public override IBuilder<$classname$> MergeFrom($classname$ other) {\r\n"
"public override Builder MergeFrom($classname$ other) {\r\n"
// Optimization: If other is the default instance, we know none of its
// fields are set so we can skip the merge.
" if (other == $classname$.DefaultInstance) return this;\r\n",
......@@ -559,11 +565,11 @@ void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) {
SortFieldsByNumber(descriptor_));
printer->Print(
"public override IBuilder<$classname$> MergeFrom(pb::CodedInputStream input) {\r\n"
"public override Builder MergeFrom(pb::CodedInputStream input) {\r\n"
" return MergeFrom(input, pb::ExtensionRegistry.Empty);\r\n"
"}\r\n"
"\r\n"
"public override IBuilder<$classname$> MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {\r\n",
"public override Builder MergeFrom(pb::CodedInputStream input, pb::ExtensionRegistry extensionRegistry) {\r\n",
"classname", ClassName(descriptor_));
printer->Indent();
......
......@@ -199,7 +199,7 @@ void ServiceGenerator::GenerateStub(io::Printer* printer) {
" controller,\r\n"
" request,\r\n"
" $output$.DefaultInstance,\r\n"
" pb::RpcUtil.GeneralizeCallback(done, $output$.DefaultInstance));\r\n"
" pb::RpcUtil.GeneralizeCallback<$output$, $output$.Builder>(done, $output$.DefaultInstance));\r\n"
"}\r\n");
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment