Commit 3f9a6f21 authored by Jon Skeet's avatar Jon Skeet

Implemented GeneratedExtension, although list handling may be incorrect.

parent 575083ae
...@@ -522,8 +522,8 @@ namespace Google.ProtocolBuffers.TestProtos { ...@@ -522,8 +522,8 @@ namespace Google.ProtocolBuffers.TestProtos {
#region Nested types #region Nested types
public static class Types { public static class Types {
public static readonly pb::GeneratedExtension<self::TestMessageSet, self::TestMessageSetExtension1> MessageSetExtension = public static readonly pb::GeneratedExtensionBase<self::TestMessageSet, self::TestMessageSetExtension1> MessageSetExtension =
pb::GeneratedExtension.CreateExtension<self::TestMessageSet, self::TestMessageSetExtension1>(Descriptor.Extensions[0]); pb::GeneratedSingleExtension<self::TestMessageSet, self::TestMessageSetExtension1>.CreateInstance(Descriptor.Extensions[0]);
} }
#endregion #endregion
...@@ -731,8 +731,8 @@ namespace Google.ProtocolBuffers.TestProtos { ...@@ -731,8 +731,8 @@ namespace Google.ProtocolBuffers.TestProtos {
#region Nested types #region Nested types
public static class Types { public static class Types {
public static readonly pb::GeneratedExtension<self::TestMessageSet, self::TestMessageSetExtension2> MessageSetExtension = public static readonly pb::GeneratedExtensionBase<self::TestMessageSet, self::TestMessageSetExtension2> MessageSetExtension =
pb::GeneratedExtension.CreateExtension<self::TestMessageSet, self::TestMessageSetExtension2>(Descriptor.Extensions[0]); pb::GeneratedSingleExtension<self::TestMessageSet, self::TestMessageSetExtension2>.CreateInstance(Descriptor.Extensions[0]);
} }
#endregion #endregion
......
...@@ -81,8 +81,8 @@ namespace Google.ProtocolBuffers.TestProtos { ...@@ -81,8 +81,8 @@ namespace Google.ProtocolBuffers.TestProtos {
#region Nested types #region Nested types
public static class Types { public static class Types {
public static readonly pb::GeneratedExtension<self::TestOptimizedForSize, int> TestExtension = public static readonly pb::GeneratedExtensionBase<self::TestOptimizedForSize, int> TestExtension =
pb::GeneratedExtension.CreateExtension<self::TestOptimizedForSize, int>(Descriptor.Extensions[0]); pb::GeneratedSingleExtension<self::TestOptimizedForSize, int>.CreateInstance(Descriptor.Extensions[0]);
} }
#endregion #endregion
......
...@@ -15,21 +15,21 @@ namespace Google.ProtocolBuffers { ...@@ -15,21 +15,21 @@ namespace Google.ProtocolBuffers {
/// <summary> /// <summary>
/// Checks if a singular extension is present. /// Checks if a singular extension is present.
/// </summary> /// </summary>
public bool HasExtension(GeneratedExtension<TMessage, TBuilder> extension) { public bool HasExtension(GeneratedExtensionBase<TMessage, TBuilder> extension) {
return extensions.HasField(extension.Descriptor); return extensions.HasField(extension.Descriptor);
} }
/// <summary> /// <summary>
/// Returns the number of elements in a repeated extension. /// Returns the number of elements in a repeated extension.
/// </summary> /// </summary>
public int GetExtensionCount<TExtension>(GeneratedExtension<TMessage, IList<TExtension>> extension) { public int GetExtensionCount<TExtension>(GeneratedExtensionBase<TMessage, IList<TExtension>> extension) {
return extensions.GetRepeatedFieldCount(extension.Descriptor); return extensions.GetRepeatedFieldCount(extension.Descriptor);
} }
/// <summary> /// <summary>
/// Returns the value of an extension. /// Returns the value of an extension.
/// </summary> /// </summary>
public TExtension GetExtension<TExtension>(GeneratedExtension<TMessage, TExtension> extension) { public TExtension GetExtension<TExtension>(GeneratedExtensionBase<TMessage, TExtension> extension) {
object value = extensions[extension.Descriptor]; object value = extensions[extension.Descriptor];
if (value == null) { if (value == null) {
return (TExtension) extension.MessageDefaultInstance; return (TExtension) extension.MessageDefaultInstance;
...@@ -41,7 +41,7 @@ namespace Google.ProtocolBuffers { ...@@ -41,7 +41,7 @@ namespace Google.ProtocolBuffers {
/// <summary> /// <summary>
/// Returns one element of a repeated extension. /// Returns one element of a repeated extension.
/// </summary> /// </summary>
public TExtension GetExtension<TExtension>(GeneratedExtension<TMessage, IList<TExtension>> extension, int index) { public TExtension GetExtension<TExtension>(GeneratedExtensionBase<TMessage, IList<TExtension>> extension, int index) {
return (TExtension) extension.SingularFromReflectionType(extensions[extension.Descriptor, index]); return (TExtension) extension.SingularFromReflectionType(extensions[extension.Descriptor, index]);
} }
......
...@@ -88,7 +88,7 @@ namespace Google.ProtocolBuffers { ...@@ -88,7 +88,7 @@ namespace Google.ProtocolBuffers {
/// <summary> /// <summary>
/// Add an extension from a generated file to the registry. /// Add an extension from a generated file to the registry.
/// </summary> /// </summary>
public void Add<TContainer, TExtension> (GeneratedExtension<TContainer, TExtension> extension) public void Add<TContainer, TExtension> (GeneratedExtensionBase<TContainer, TExtension> extension)
where TContainer : IMessage<TContainer> { where TContainer : IMessage<TContainer> {
if (extension.Descriptor.MappedType == MappedType.Message) { if (extension.Descriptor.MappedType == MappedType.Message) {
Add(new ExtensionInfo(extension.Descriptor, extension.MessageDefaultInstance)); Add(new ExtensionInfo(extension.Descriptor, extension.MessageDefaultInstance));
......
using Google.ProtocolBuffers.Descriptors; using System;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using System.Text;
using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers { namespace Google.ProtocolBuffers {
public static class GeneratedExtension {
public static GeneratedExtension<TContainer, TExtension> CreateExtension<TContainer, TExtension>(FieldDescriptor descriptor)
where TContainer : IMessage<TContainer> {
if (descriptor.IsRepeated) {
throw new ArgumentException("Must call CreateRepeatedGeneratedExtension() for repeated types.");
}
return new GeneratedExtension<TContainer, TExtension>(descriptor);
}
public static GeneratedExtension<TContainer, IList<TExtension>> CreateRepeatedExtension<TContainer, TExtension>(FieldDescriptor descriptor)
where TContainer : IMessage<TContainer> {
if (descriptor.IsRepeated) {
throw new ArgumentException("Must call CreateRepeatedGeneratedExtension() for repeated types.");
}
return new GeneratedExtension<TContainer, IList<TExtension>>(descriptor);
}
}
/// <summary> /// <summary>
/// Base class for all generated extensions. /// Base type for all generated extensions.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// The protocol compiler generates a static singleton instance of this /// The protocol compiler generates a static singleton instance of this
...@@ -39,42 +20,32 @@ namespace Google.ProtocolBuffers { ...@@ -39,42 +20,32 @@ namespace Google.ProtocolBuffers {
/// optional int32 bar; /// optional int32 bar;
/// } /// }
/// </code> /// </code>
/// Then MyProto.Foo.Bar has type GeneratedExtension&lt;MyProto.Foo,int&gt;. /// Then MyProto.Foo.Bar has type GeneratedExtensionBase&lt;MyProto.Foo,int&gt;.
/// <para /> /// <para />
/// In general, users should ignore the details of this type, and /// In general, users should ignore the details of this type, and
/// simply use the static singletons as parmaeters to the extension accessors /// simply use the static singletons as parameters to the extension accessors
/// in ExtendableMessage and ExtendableBuilder. /// in ExtendableMessage and ExtendableBuilder.
/// The interface implemented by both GeneratedException and GeneratedRepeatException,
/// to make it easier to cope with repeats separately.
/// </remarks> /// </remarks>
public class GeneratedExtension<TContainer, TExtension> where TContainer : IMessage<TContainer> { public abstract class GeneratedExtensionBase<TContainer, TExtension> {
private readonly IMessage messageDefaultInstance;
private readonly FieldDescriptor descriptor; private readonly FieldDescriptor descriptor;
private readonly IMessage messageDefaultInstance;
internal GeneratedExtension(FieldDescriptor descriptor) { protected GeneratedExtensionBase(FieldDescriptor descriptor) {
if (!descriptor.IsExtension) { if (!descriptor.IsExtension) {
throw new ArgumentException("GeneratedExtension given a regular (non-extension) field."); throw new ArgumentException("GeneratedExtension given a regular (non-extension) field.");
} }
this.descriptor = descriptor; this.descriptor = descriptor;
if (descriptor.MappedType == MappedType.Message) {
switch (descriptor.MappedType) { PropertyInfo defaultInstanceProperty = typeof(TExtension)
case MappedType.Message: .GetProperty("DefaultInstance", BindingFlags.Static | BindingFlags.Public);
PropertyInfo defaultInstanceProperty = typeof(TExtension) if (defaultInstanceProperty == null) {
.GetProperty("DefaultInstance", BindingFlags.Static | BindingFlags.Public); throw new ArgumentException("No public static DefaultInstance property for type " + typeof(TExtension).Name);
if (defaultInstanceProperty == null) { }
throw new ArgumentException("No public static DefaultInstance property for type " + typeof(TExtension).Name); messageDefaultInstance = (IMessage)defaultInstanceProperty.GetValue(null, null);
}
messageDefaultInstance = (IMessage) defaultInstanceProperty.GetValue(null, null);
break;
case MappedType.Enum:
// FIXME(jonskeet): May not need this
//enumValueOf = getMethodOrDie(type, "valueOf",
// EnumValueDescriptor.class);
//enumGetValueDescriptor = getMethodOrDie(type, "getValueDescriptor");
messageDefaultInstance = null;
break;
default:
messageDefaultInstance = null;
break;
} }
} }
...@@ -82,16 +53,36 @@ namespace Google.ProtocolBuffers { ...@@ -82,16 +53,36 @@ namespace Google.ProtocolBuffers {
get { return descriptor; } get { return descriptor; }
} }
/// <summary>
/// Returns the default message instance for extensions which are message types.
/// </summary>
public IMessage MessageDefaultInstance { public IMessage MessageDefaultInstance {
get { return messageDefaultInstance; } get { return messageDefaultInstance; }
} }
internal object SingularFromReflectionType(object p) { public object SingularFromReflectionType(object value) {
throw new System.NotImplementedException(); switch (Descriptor.MappedType) {
case MappedType.Message:
if (value is TExtension) {
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.CreateBuilderForType()
.MergeFrom((IMessage)value).Build();
}
case MappedType.Enum:
// Just return a boxed int - that can be unboxed to the enum
return ((EnumValueDescriptor) value).Number;
default:
return value;
}
} }
internal object FromReflectionType(object value) { public abstract object FromReflectionType(object value);
throw new System.NotImplementedException();
}
} }
} }
\ No newline at end of file
using System;
using System.Collections.Generic;
using Google.ProtocolBuffers.Descriptors;
using System.Collections;
namespace Google.ProtocolBuffers {
/// <summary>
/// Class used to represent repeat extensions in generated classes.
/// </summary>
public class GeneratedRepeatExtension<TContainer, TExtensionElement> : GeneratedExtensionBase<TContainer, IList<TExtensionElement>> {
private GeneratedRepeatExtension(FieldDescriptor field) : base(field) {
}
public static GeneratedExtensionBase<TContainer, IList<TExtensionElement>> CreateInstance(FieldDescriptor descriptor) {
if (descriptor.IsRepeated) {
throw new ArgumentException("Must call GeneratedRepeatExtension.CreateInstance() for repeated types.");
}
return new GeneratedRepeatExtension<TContainer, TExtensionElement>(descriptor);
}
/// <summary>
/// Converts the list to the right type.
/// TODO(jonskeet): Check where this is used, and whether we need to convert
/// for primitive types.
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public override object FromReflectionType(object value) {
if (Descriptor.MappedType == MappedType.Message ||
Descriptor.MappedType == MappedType.Enum) {
// Must convert the whole list.
List<TExtensionElement> result = new List<TExtensionElement>();
foreach (object element in (IEnumerable) value) {
((IList) result).Add(SingularFromReflectionType(element));
}
return result;
} else {
return value;
}
}
}
}
using System;
using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers {
/// <summary>
/// Generated extension for a singular field.
/// </remarks>
public class GeneratedSingleExtension<TContainer, TExtension> : GeneratedExtensionBase<TContainer, TExtension>
where TContainer : IMessage<TContainer> {
internal GeneratedSingleExtension(FieldDescriptor descriptor) : base(descriptor) {
}
public static GeneratedSingleExtension<TContainer, TExtension> CreateInstance(FieldDescriptor descriptor) {
if (descriptor.IsRepeated) {
throw new ArgumentException("Must call GeneratedRepeateExtension.CreateInstance() for repeated types.");
}
return new GeneratedSingleExtension<TContainer, TExtension>(descriptor);
}
public override object FromReflectionType(object value) {
return base.SingularFromReflectionType(value);
}
}
}
...@@ -82,9 +82,11 @@ ...@@ -82,9 +82,11 @@
<Compile Include="FieldAccess\RepeatedMessageAccessor.cs" /> <Compile Include="FieldAccess\RepeatedMessageAccessor.cs" />
<Compile Include="FieldSet.cs" /> <Compile Include="FieldSet.cs" />
<Compile Include="GeneratedBuilder.cs" /> <Compile Include="GeneratedBuilder.cs" />
<Compile Include="GeneratedExtension.cs" /> <Compile Include="GeneratedSingleExtension.cs" />
<Compile Include="GeneratedMessage.cs" /> <Compile Include="GeneratedMessage.cs" />
<Compile Include="GeneratedRepeatException.cs" />
<Compile Include="IBuilder.cs" /> <Compile Include="IBuilder.cs" />
<Compile Include="GeneratedExtensionBase.cs" />
<Compile Include="IMessage.cs" /> <Compile Include="IMessage.cs" />
<Compile Include="InvalidProtocolBufferException.cs" /> <Compile Include="InvalidProtocolBufferException.cs" />
<Compile Include="IRpcChannel.cs" /> <Compile Include="IRpcChannel.cs" />
......
...@@ -57,12 +57,12 @@ void ExtensionGenerator::Generate(io::Printer* printer) { ...@@ -57,12 +57,12 @@ void ExtensionGenerator::Generate(io::Printer* printer) {
if (descriptor_->is_repeated()) { if (descriptor_->is_repeated()) {
printer->Print(vars, printer->Print(vars,
"public static readonly\r\n" "public static readonly\r\n"
" pb::GeneratedExtension<$containing_type$, scg::IList<$type$>> name =\r\n" " pb::GeneratedExtensionBase<$containing_type$, scg::IList<$type$>> name =\r\n"
" pb::GeneratedExtension.CreateRepeatedExtension<$containing_type$, $type$>(Descriptor.Extensions[$index$]);\r\n"); " pb::GeneratedRepeatExtension<$containing_type$, $type$>.CreateInstance(Descriptor.Extensions[$index$]);\r\n");
} else { } else {
printer->Print(vars, printer->Print(vars,
"public static readonly pb::GeneratedExtension<$containing_type$, $type$> $name$ =\r\n" "public static readonly pb::GeneratedExtensionBase<$containing_type$, $type$> $name$ =\r\n"
" pb::GeneratedExtension.CreateExtension<$containing_type$, $type$>(Descriptor.Extensions[$index$]);\r\n"); " pb::GeneratedSingleExtension<$containing_type$, $type$>.CreateInstance(Descriptor.Extensions[$index$]);\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