Commit 575083ae authored by Jon Skeet's avatar Jon Skeet

Initial support for services and extensions. Incomplete, but enough to get…

Initial support for services and extensions. Incomplete, but enough to get generated unit test files to compile.
parent 1353315d
...@@ -48,6 +48,12 @@ ...@@ -48,6 +48,12 @@
<Compile Include="CodedInputStreamTest.cs" /> <Compile Include="CodedInputStreamTest.cs" />
<Compile Include="CodedOutputStreamTest.cs" /> <Compile Include="CodedOutputStreamTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TestProtos\UnitTestEmbedOptimizeForProtoFile.cs" />
<Compile Include="TestProtos\UnitTestImportProtoFile.cs" />
<Compile Include="TestProtos\UnitTestMessageSetProtoFile.cs" />
<Compile Include="TestProtos\UnitTestOptimizeForProtoFile.cs" />
<Compile Include="TestProtos\UnitTestProtoFile.cs" />
<Compile Include="TestUtil.cs" />
<Compile Include="WireFormatTest.cs" /> <Compile Include="WireFormatTest.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
......
This diff is collapsed.
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace Google.ProtocolBuffers {
internal static class TestUtil {
private static DirectoryInfo testDataDirectory;
internal static DirectoryInfo TestDataDirectory {
get {
if (testDataDirectory != null) {
return testDataDirectory;
}
DirectoryInfo ancestor = new DirectoryInfo(".");
// Search each parent directory looking for "src/google/protobuf".
while (ancestor != null) {
string candidate = Path.Combine(ancestor.FullName, "src/google/protobuf");
if (Directory.Exists(candidate)) {
testDataDirectory = new DirectoryInfo(candidate);
return testDataDirectory;
}
ancestor = ancestor.Parent;
}
// TODO(jonskeet): Come up with a better exception to throw
throw new Exception("Unable to find directory containing test files");
}
}
}
}
...@@ -142,6 +142,7 @@ namespace Google.ProtocolBuffers { ...@@ -142,6 +142,7 @@ namespace Google.ProtocolBuffers {
/// Read a double field from the stream. /// Read a double field from the stream.
/// </summary> /// </summary>
public double ReadDouble() { public double ReadDouble() {
// TODO(jonskeet): Test this on different endiannesses
return BitConverter.Int64BitsToDouble((long) ReadRawLittleEndian64()); return BitConverter.Int64BitsToDouble((long) ReadRawLittleEndian64());
} }
...@@ -149,9 +150,10 @@ namespace Google.ProtocolBuffers { ...@@ -149,9 +150,10 @@ namespace Google.ProtocolBuffers {
/// Read a float field from the stream. /// Read a float field from the stream.
/// </summary> /// </summary>
public float ReadFloat() { public float ReadFloat() {
//return Float.intBitsToFloat(readRawLittleEndian32()); // TODO(jonskeet): Test this on different endiannesses
// FIXME implement! uint raw = ReadRawLittleEndian32();
throw new NotImplementedException(); byte[] rawBytes = BitConverter.GetBytes(raw);
return BitConverter.ToSingle(rawBytes, 0);
} }
/// <summary> /// <summary>
......
...@@ -98,6 +98,7 @@ namespace Google.ProtocolBuffers { ...@@ -98,6 +98,7 @@ namespace Google.ProtocolBuffers {
/// Writes a double field value, including tag, to the stream. /// Writes a double field value, including tag, to the stream.
/// </summary> /// </summary>
public void WriteDouble(int fieldNumber, double value) { public void WriteDouble(int fieldNumber, double value) {
// TODO(jonskeet): Test this on different endiannesses
WriteTag(fieldNumber, WireFormat.WireType.Fixed64); WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
WriteRawLittleEndian64((ulong)BitConverter.DoubleToInt64Bits(value)); WriteRawLittleEndian64((ulong)BitConverter.DoubleToInt64Bits(value));
} }
...@@ -107,8 +108,10 @@ namespace Google.ProtocolBuffers { ...@@ -107,8 +108,10 @@ namespace Google.ProtocolBuffers {
/// </summary> /// </summary>
public void WriteFloat(int fieldNumber, float value) { public void WriteFloat(int fieldNumber, float value) {
WriteTag(fieldNumber, WireFormat.WireType.Fixed32); WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
// FIXME: How do we convert a single to 32 bits? (Without unsafe code) // TODO(jonskeet): Test this on different endiannesses
//WriteRawLittleEndian32(BitConverter.SingleT(value)); byte[] rawBytes = BitConverter.GetBytes(value);
uint asInteger = BitConverter.ToUInt32(rawBytes, 0);
WriteRawLittleEndian32(asInteger);
} }
/// <summary> /// <summary>
...@@ -434,7 +437,7 @@ namespace Google.ProtocolBuffers { ...@@ -434,7 +437,7 @@ namespace Google.ProtocolBuffers {
/// Compute the number of bytes that would be needed to encode a /// Compute the number of bytes that would be needed to encode a
/// fixed64 field, including the tag. /// fixed64 field, including the tag.
/// </summary> /// </summary>
public static int ComputeFixed64Size(int fieldNumber, long value) { public static int ComputeFixed64Size(int fieldNumber, ulong value) {
return ComputeTagSize(fieldNumber) + LittleEndian64Size; return ComputeTagSize(fieldNumber) + LittleEndian64Size;
} }
...@@ -442,7 +445,7 @@ namespace Google.ProtocolBuffers { ...@@ -442,7 +445,7 @@ namespace Google.ProtocolBuffers {
/// Compute the number of bytes that would be needed to encode a /// Compute the number of bytes that would be needed to encode a
/// fixed32 field, including the tag. /// fixed32 field, including the tag.
/// </summary> /// </summary>
public static int ComputeFixed32Size(int fieldNumber, int value) { public static int ComputeFixed32Size(int fieldNumber, uint value) {
return ComputeTagSize(fieldNumber) + LittleEndian32Size; return ComputeTagSize(fieldNumber) + LittleEndian32Size;
} }
...@@ -625,8 +628,8 @@ namespace Google.ProtocolBuffers { ...@@ -625,8 +628,8 @@ namespace Google.ProtocolBuffers {
case FieldType.Int64: return ComputeInt64Size(fieldNumber, (long)value); case FieldType.Int64: return ComputeInt64Size(fieldNumber, (long)value);
case FieldType.UInt64: return ComputeUInt64Size(fieldNumber, (ulong)value); case FieldType.UInt64: return ComputeUInt64Size(fieldNumber, (ulong)value);
case FieldType.Int32: return ComputeInt32Size(fieldNumber, (int)value); case FieldType.Int32: return ComputeInt32Size(fieldNumber, (int)value);
case FieldType.Fixed64: return ComputeFixed64Size(fieldNumber, (long)value); case FieldType.Fixed64: return ComputeFixed64Size(fieldNumber, (ulong)value);
case FieldType.Fixed32: return ComputeFixed32Size(fieldNumber, (int)value); case FieldType.Fixed32: return ComputeFixed32Size(fieldNumber, (uint)value);
case FieldType.Bool: return ComputeBoolSize(fieldNumber, (bool)value); case FieldType.Bool: return ComputeBoolSize(fieldNumber, (bool)value);
case FieldType.String: return ComputeStringSize(fieldNumber, (string)value); case FieldType.String: return ComputeStringSize(fieldNumber, (string)value);
case FieldType.Group: return ComputeGroupSize(fieldNumber, (IMessage)value); case FieldType.Group: return ComputeGroupSize(fieldNumber, (IMessage)value);
......
...@@ -3,9 +3,10 @@ ...@@ -3,9 +3,10 @@
namespace Google.ProtocolBuffers.Descriptors { namespace Google.ProtocolBuffers.Descriptors {
/// <summary> /// <summary>
/// Allows enum values to express the index within their descriptor. /// Allows enum values to express the index within their descriptor.
/// TODO(jonskeet): Consider removing this. I don't think we need it after all.
/// </summary> /// </summary>
[AttributeUsage(AttributeTargets.Field)] [AttributeUsage(AttributeTargets.Field)]
internal class EnumDescriptorIndexAttribute : Attribute { public class EnumDescriptorIndexAttribute : Attribute {
readonly int index; readonly int index;
internal int Index { internal int Index {
......
using System;
using System.Collections.Generic;
using System.Text;
namespace Google.ProtocolBuffers {
public class DynamicMessage {
internal static object GetDefaultInstance(Google.ProtocolBuffers.Descriptors.MessageDescriptor messageDescriptor) {
throw new NotImplementedException();
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using Google.ProtocolBuffers.Descriptors;
using Google.ProtocolBuffers.Collections;
namespace Google.ProtocolBuffers {
public abstract class ExtendableMessage<TMessage,TBuilder> : GeneratedMessage<TMessage,TBuilder>
where TMessage : GeneratedMessage<TMessage, TBuilder>
where TBuilder : IBuilder<TMessage> {
protected ExtendableMessage() {}
private readonly FieldSet extensions = FieldSet.CreateFieldSet();
/// <summary>
/// Checks if a singular extension is present.
/// </summary>
public bool HasExtension(GeneratedExtension<TMessage, TBuilder> extension) {
return extensions.HasField(extension.Descriptor);
}
/// <summary>
/// Returns the number of elements in a repeated extension.
/// </summary>
public int GetExtensionCount<TExtension>(GeneratedExtension<TMessage, IList<TExtension>> extension) {
return extensions.GetRepeatedFieldCount(extension.Descriptor);
}
/// <summary>
/// Returns the value of an extension.
/// </summary>
public TExtension GetExtension<TExtension>(GeneratedExtension<TMessage, TExtension> extension) {
object value = extensions[extension.Descriptor];
if (value == null) {
return (TExtension) extension.MessageDefaultInstance;
} else {
return (TExtension) extension.FromReflectionType(value);
}
}
/// <summary>
/// Returns one element of a repeated extension.
/// </summary>
public TExtension GetExtension<TExtension>(GeneratedExtension<TMessage, IList<TExtension>> extension, int index) {
return (TExtension) extension.SingularFromReflectionType(extensions[extension.Descriptor, index]);
}
/// <summary>
/// Called by subclasses to check if all extensions are initialized.
/// </summary>
protected bool ExtensionsAreInitialized {
get { return extensions.IsInitialized; }
}
#region Reflection
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;
}
return Dictionaries.AsReadOnly(result);
}
}
public override bool HasField(FieldDescriptor field) {
if (field.IsExtension) {
VerifyContainingType(field);
return extensions.HasField(field);
} else {
return base.HasField(field);
}
}
public override object this[FieldDescriptor field] {
get {
if (field.IsExtension) {
VerifyContainingType(field);
object value = extensions[field];
if (value == null) {
// Lacking an ExtensionRegistry, we have no way to determine the
// extension's real type, so we return a DynamicMessage.
// TODO(jonskeet): Work out what this means
return DynamicMessage.GetDefaultInstance(field.MessageType);
} else {
return value;
}
} else {
return base[field];
}
}
}
public override int GetRepeatedFieldCount(FieldDescriptor field) {
if (field.IsExtension) {
VerifyContainingType(field);
return extensions.GetRepeatedFieldCount(field);
} else {
return base.GetRepeatedFieldCount(field);
}
}
public override object this[FieldDescriptor field, int index] {
get {
if (field.IsExtension) {
VerifyContainingType(field);
return extensions[field, index];
} else {
return base[field, index];
}
}
}
private void VerifyContainingType(FieldDescriptor field) {
if (field.ContainingType != DescriptorForType) {
throw new ArgumentException("FieldDescriptor does not match message type.");
}
}
#endregion
/// <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<FieldDescriptor, object>> iterator;
readonly FieldSet extensions;
KeyValuePair<FieldDescriptor, object>? next = null;
internal ExtensionWriter(ExtendableMessage<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(ExtendableMessage<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; }
}
}
}
...@@ -30,6 +30,10 @@ namespace Google.ProtocolBuffers { ...@@ -30,6 +30,10 @@ namespace Google.ProtocolBuffers {
this.fields = fields; this.fields = fields;
} }
public static FieldSet CreateFieldSet() {
return new FieldSet(new Dictionary<FieldDescriptor, object>());
}
/// <summary> /// <summary>
/// Makes this FieldSet immutable, and returns it for convenience. Any /// Makes this FieldSet immutable, and returns it for convenience. Any
/// mutable repeated fields are made immutable, as well as the map itself. /// mutable repeated fields are made immutable, as well as the map itself.
...@@ -395,6 +399,13 @@ namespace Google.ProtocolBuffers { ...@@ -395,6 +399,13 @@ namespace Google.ProtocolBuffers {
((IList<object>) list).Add(value); ((IList<object>) list).Add(value);
} }
/// <summary>
/// Returns an enumerator for the field map. Used to write the fields out.
/// </summary>
internal IEnumerator<KeyValuePair<FieldDescriptor, object>> GetEnumerator() {
return fields.GetEnumerator();
}
/// <summary> /// <summary>
/// See <see cref="IMessage.IsInitialized" /> /// See <see cref="IMessage.IsInitialized" />
/// </summary> /// </summary>
......
...@@ -23,7 +23,7 @@ namespace Google.ProtocolBuffers { ...@@ -23,7 +23,7 @@ namespace Google.ProtocolBuffers {
protected abstract TMessage MessageBeingBuilt { get; } protected abstract TMessage MessageBeingBuilt { get; }
protected internal FieldAccessorTable InternalFieldAccessors { protected internal FieldAccessorTable InternalFieldAccessors {
get { return MessageBeingBuilt.InternalFieldAccessors; } get { return MessageBeingBuilt.FieldAccesseorsFromBuilder; }
} }
public override bool Initialized { public override bool Initialized {
...@@ -190,6 +190,16 @@ namespace Google.ProtocolBuffers { ...@@ -190,6 +190,16 @@ namespace Google.ProtocolBuffers {
return this; return this;
} }
public virtual IBuilder<TMessage> MergeFrom(CodedInputStream input) {
((IBuilder)this).MergeFrom(input);
return this;
}
public virtual IBuilder<TMessage> MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry) {
((IBuilder)this).MergeFrom(input, extensionRegistry);
return this;
}
/// <summary> /// <summary>
/// Like Build(), but will wrap UninitializedMessageException in /// Like Build(), but will wrap UninitializedMessageException in
/// InvalidProtocolBufferException. /// InvalidProtocolBufferException.
...@@ -217,7 +227,8 @@ namespace Google.ProtocolBuffers { ...@@ -217,7 +227,8 @@ namespace Google.ProtocolBuffers {
public abstract IBuilder<TMessage> Clone(); public abstract IBuilder<TMessage> Clone();
public abstract new IBuilder<TMessage> Clear(); public abstract new IBuilder<TMessage> Clear();
public abstract TMessage DefaultInstanceForType { get; } public abstract TMessage DefaultInstanceForType { get; }
public abstract IBuilder<TMessage> MergeFrom(CodedInputStream input);
public abstract IBuilder<TMessage> MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry); public abstract class ExtendableBuilder : GeneratedBuilder<TMessage, TBuilder> {
}
} }
} }
using Google.ProtocolBuffers.Descriptors; using Google.ProtocolBuffers.Descriptors;
using System;
using System.Collections.Generic;
using System.Reflection;
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 class for all generated extensions.
/// </summary> /// </summary>
...@@ -24,8 +46,52 @@ namespace Google.ProtocolBuffers { ...@@ -24,8 +46,52 @@ namespace Google.ProtocolBuffers {
/// in ExtendableMessage and ExtendableBuilder. /// in ExtendableMessage and ExtendableBuilder.
/// </remarks> /// </remarks>
public class GeneratedExtension<TContainer, TExtension> where TContainer : IMessage<TContainer> { public class GeneratedExtension<TContainer, TExtension> where TContainer : IMessage<TContainer> {
public FieldDescriptor Descriptor; private readonly IMessage messageDefaultInstance;
private readonly FieldDescriptor descriptor;
internal GeneratedExtension(FieldDescriptor descriptor) {
if (!descriptor.IsExtension) {
throw new ArgumentException("GeneratedExtension given a regular (non-extension) field.");
}
this.descriptor = descriptor;
switch (descriptor.MappedType) {
case MappedType.Message:
PropertyInfo defaultInstanceProperty = typeof(TExtension)
.GetProperty("DefaultInstance", BindingFlags.Static | BindingFlags.Public);
if (defaultInstanceProperty == null) {
throw new ArgumentException("No public static DefaultInstance property for type " + typeof(TExtension).Name);
}
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;
}
}
public FieldDescriptor Descriptor {
get { return descriptor; }
}
public IMessage MessageDefaultInstance {
get { return messageDefaultInstance; }
}
internal object SingularFromReflectionType(object p) {
throw new System.NotImplementedException();
}
public IMessage MessageDefaultInstance; internal object FromReflectionType(object value) {
throw new System.NotImplementedException();
}
} }
} }
...@@ -14,11 +14,16 @@ namespace Google.ProtocolBuffers { ...@@ -14,11 +14,16 @@ namespace Google.ProtocolBuffers {
/// can ignore this class as an implementation detail. /// can ignore this class as an implementation detail.
/// </summary> /// </summary>
public abstract class GeneratedMessage<TMessage, TBuilder> : AbstractMessage, IMessage<TMessage> public abstract class GeneratedMessage<TMessage, TBuilder> : AbstractMessage, IMessage<TMessage>
where TMessage : GeneratedMessage<TMessage, TBuilder> where TBuilder : IBuilder<TMessage> { where TMessage : GeneratedMessage<TMessage, TBuilder>
where TBuilder : IBuilder<TMessage> {
private UnknownFieldSet unknownFields = UnknownFieldSet.DefaultInstance; private UnknownFieldSet unknownFields = UnknownFieldSet.DefaultInstance;
protected internal abstract FieldAccessorTable InternalFieldAccessors { get; } internal FieldAccessorTable FieldAccesseorsFromBuilder {
get { return InternalFieldAccessors; }
}
protected abstract FieldAccessorTable InternalFieldAccessors { get; }
public override MessageDescriptor DescriptorForType { public override MessageDescriptor DescriptorForType {
get { return InternalFieldAccessors.Descriptor; } get { return InternalFieldAccessors.Descriptor; }
...@@ -36,7 +41,7 @@ namespace Google.ProtocolBuffers { ...@@ -36,7 +41,7 @@ namespace Google.ProtocolBuffers {
public abstract IBuilder<TMessage> CreateBuilderForType(); public abstract IBuilder<TMessage> CreateBuilderForType();
private IDictionary<FieldDescriptor, Object> GetMutableFieldMap() { internal IDictionary<FieldDescriptor, Object> GetMutableFieldMap() {
// Use a SortedList so we'll end up serializing fields in order // Use a SortedList so we'll end up serializing fields in order
var ret = new SortedList<FieldDescriptor, object>(); var ret = new SortedList<FieldDescriptor, object>();
...@@ -83,6 +88,6 @@ namespace Google.ProtocolBuffers { ...@@ -83,6 +88,6 @@ namespace Google.ProtocolBuffers {
/// </summary> /// </summary>
internal void SetUnknownFields(UnknownFieldSet fieldSet) { internal void SetUnknownFields(UnknownFieldSet fieldSet) {
unknownFields = fieldSet; unknownFields = fieldSet;
} }
} }
} }
using System;
using System.Collections.Generic;
using System.Text;
using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers {
/// <summary>
/// TODO(jonskeet): Do this properly.
/// </summary>
public interface IRpcChannel {
void CallMethod<T>(MethodDescriptor method, IRpcController controller,
IMessage request, IMessage responsePrototype, Action<T> done);
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace Google.ProtocolBuffers {
public interface IRpcController {
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace Google.ProtocolBuffers {
public interface IService {
// TODO(jonskeet): Fill this in
}
}
...@@ -67,6 +67,8 @@ ...@@ -67,6 +67,8 @@
<Compile Include="Descriptors\MethodDescriptor.cs" /> <Compile Include="Descriptors\MethodDescriptor.cs" />
<Compile Include="Descriptors\PackageDescriptor.cs" /> <Compile Include="Descriptors\PackageDescriptor.cs" />
<Compile Include="Descriptors\ServiceDescriptor.cs" /> <Compile Include="Descriptors\ServiceDescriptor.cs" />
<Compile Include="DynamicMessage.cs" />
<Compile Include="ExtendableMessage.cs" />
<Compile Include="ExtensionInfo.cs" /> <Compile Include="ExtensionInfo.cs" />
<Compile Include="ExtensionRegistry.cs" /> <Compile Include="ExtensionRegistry.cs" />
<Compile Include="FieldAccess\SingleEnumAccessor.cs" /> <Compile Include="FieldAccess\SingleEnumAccessor.cs" />
...@@ -85,7 +87,11 @@ ...@@ -85,7 +87,11 @@
<Compile Include="IBuilder.cs" /> <Compile Include="IBuilder.cs" />
<Compile Include="IMessage.cs" /> <Compile Include="IMessage.cs" />
<Compile Include="InvalidProtocolBufferException.cs" /> <Compile Include="InvalidProtocolBufferException.cs" />
<Compile Include="IRpcChannel.cs" />
<Compile Include="IRpcController.cs" />
<Compile Include="IService.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RpcUtil.cs" />
<Compile Include="TextFormat.cs" /> <Compile Include="TextFormat.cs" />
<Compile Include="TextGenerator.cs" /> <Compile Include="TextGenerator.cs" />
<Compile Include="UninitializedMessageException.cs" /> <Compile Include="UninitializedMessageException.cs" />
......
using System;
using System.Collections.Generic;
using System.Text;
namespace Google.ProtocolBuffers {
public static class RpcUtil {
/// <summary>
/// Converts an Action[IMessage] to an Action[T].
/// </summary>
public static Action<T> SpecializeCallback<T>(Action<IMessage> action)
where T : IMessage<T> {
return message => action(message);
}
/// <summary>
/// Converts an Action[T] to an Action[IMessage].
/// The generalized action will accept any message object which has
/// the same descriptor, and will convert it to the correct class
/// before calling the original action. However, if the generalized
/// 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> {
return message => {
T castMessage = message as T;
if (castMessage == null) {
castMessage = (T) defaultInstance.CreateBuilderForType().MergeFrom(message).Build();
}
action(castMessage);
};
}
}
}
...@@ -155,25 +155,18 @@ namespace Google.ProtocolBuffers { ...@@ -155,25 +155,18 @@ namespace Google.ProtocolBuffers {
UnknownField field = entry.Value; UnknownField field = entry.Value;
foreach (ulong value in field.VarintList) { foreach (ulong value in field.VarintList) {
generator.Print(entry.Key.ToString()); generator.Print(prefix);
generator.Print(": ");
generator.Print(value.ToString()); generator.Print(value.ToString());
generator.Print("\n"); generator.Print("\n");
} }
foreach (uint value in field.Fixed32List) { foreach (uint value in field.Fixed32List) {
generator.Print(entry.Key.ToString()); generator.Print(prefix);
generator.Print(": "); generator.Print(string.Format("0x{0:x8}", value));
// FIXME(jonskeet): Get format of this right; in Java it's %08x. Find out what this means
// Also check we're okay in terms of signed/unsigned.
generator.Print(string.Format("0x{0:x}", value));
generator.Print("\n"); generator.Print("\n");
} }
foreach (ulong value in field.Fixed64List) { foreach (ulong value in field.Fixed64List) {
generator.Print(entry.Key.ToString()); generator.Print(prefix);
generator.Print(": "); generator.Print(string.Format("0x{0:x16}", value));
// FIXME(jonskeet): Get format of this right; in Java it's %016x. Find out what this means
// Also check we're okay in terms of signed/unsigned.
generator.Print(string.Format("0x{0:x}", value));
generator.Print("\n"); generator.Print("\n");
} }
foreach (ByteString value in field.LengthDelimitedList) { foreach (ByteString value in field.LengthDelimitedList) {
...@@ -193,7 +186,6 @@ namespace Google.ProtocolBuffers { ...@@ -193,7 +186,6 @@ namespace Google.ProtocolBuffers {
} }
} }
internal static ulong ParseUInt64(string text) { internal static ulong ParseUInt64(string text) {
return (ulong) ParseInteger(text, true, false); return (ulong) ParseInteger(text, true, false);
} }
......
...@@ -127,10 +127,10 @@ namespace Google.ProtocolBuffers { ...@@ -127,10 +127,10 @@ namespace Google.ProtocolBuffers {
foreach (ulong value in varintList) { foreach (ulong value in varintList) {
result += CodedOutputStream.ComputeUInt64Size(fieldNumber, value); result += CodedOutputStream.ComputeUInt64Size(fieldNumber, value);
} }
foreach (int value in fixed32List) { foreach (uint value in fixed32List) {
result += CodedOutputStream.ComputeFixed32Size(fieldNumber, value); result += CodedOutputStream.ComputeFixed32Size(fieldNumber, value);
} }
foreach (long value in fixed64List) { foreach (ulong value in fixed64List) {
result += CodedOutputStream.ComputeFixed64Size(fieldNumber, value); result += CodedOutputStream.ComputeFixed64Size(fieldNumber, value);
} }
foreach (ByteString value in lengthDelimitedList) { foreach (ByteString value in lengthDelimitedList) {
......
...@@ -69,8 +69,9 @@ void EnumGenerator::Generate(io::Printer* printer) { ...@@ -69,8 +69,9 @@ void EnumGenerator::Generate(io::Printer* printer) {
vars["number"] = SimpleItoa(canonical_values_[i]->number()); vars["number"] = SimpleItoa(canonical_values_[i]->number());
// TODO(jonskeet): Change CONSTANT_CASE into PascalCase // TODO(jonskeet): Change CONSTANT_CASE into PascalCase
// TODO(jonskeet): I don't think we need EnumDescriptorIndex after all
printer->Print(vars, printer->Print(vars,
"[pbd::EnumDescriptorIndex($index$)]\r\n" //"[pbd::EnumDescriptorIndex($index$)]\r\n"
"$name$ = $number$,\r\n"); "$name$ = $number$,\r\n");
} }
printer->Outdent(); printer->Outdent();
......
...@@ -178,11 +178,11 @@ GenerateBuilderMembers(io::Printer* printer) const { ...@@ -178,11 +178,11 @@ GenerateBuilderMembers(io::Printer* printer) const {
// could hold on to the returned list and modify it after the message // could hold on to the returned list and modify it after the message
// has been built, thus mutating the message which is supposed to be // has been built, thus mutating the message which is supposed to be
// immutable. // immutable.
"public global::System.Collections.Generic::IList<$type$> $capitalized_name$List {\r\n" "public scg::IList<$type$> $capitalized_name$List {\r\n"
" get { return pbc::Lists.AsReadOnly(result.$name$_); }\r\n" " get { return pbc::Lists.AsReadOnly(result.$name$_); }\r\n"
"}\r\n" "}\r\n"
"public int $capitalized_name$Count {\r\n" "public int $capitalized_name$Count {\r\n"
" get { return result.get$capitalized_name$Count; } \r\n" " get { return result.$capitalized_name$Count; } \r\n"
"}\r\n" "}\r\n"
"public $type$ Get$capitalized_name$(int index) {\r\n" "public $type$ Get$capitalized_name$(int index) {\r\n"
" return result.Get$capitalized_name$(index);\r\n" " return result.Get$capitalized_name$(index);\r\n"
...@@ -191,7 +191,7 @@ GenerateBuilderMembers(io::Printer* printer) const { ...@@ -191,7 +191,7 @@ GenerateBuilderMembers(io::Printer* printer) const {
" result.$name$_[index] = value;\r\n" " result.$name$_[index] = value;\r\n"
" return this;\r\n" " return this;\r\n"
"}\r\n" "}\r\n"
"public Builder add$capitalized_name$($type$ value) {\r\n" "public Builder Add$capitalized_name$($type$ value) {\r\n"
" if (result.$name$_.Count == 0) {\r\n" " if (result.$name$_.Count == 0) {\r\n"
" result.$name$_ = new scg::List<$type$>();\r\n" " result.$name$_ = new scg::List<$type$>();\r\n"
" }\r\n" " }\r\n"
...@@ -232,9 +232,9 @@ void RepeatedEnumFieldGenerator:: ...@@ -232,9 +232,9 @@ void RepeatedEnumFieldGenerator::
GenerateParsingCode(io::Printer* printer) const { GenerateParsingCode(io::Printer* printer) const {
printer->Print(variables_, printer->Print(variables_,
"int rawValue = input.ReadEnum();\r\n" "int rawValue = input.ReadEnum();\r\n"
"$type$ value = $type$.valueOf(rawValue);\r\n" "$type$ value = ($type$) rawValue;\r\n"
"if (value == null) {\r\n" "if (!global::System.Enum.IsDefined(typeof($type$), value)) {\r\n"
" unknownFields.MergeVarintField($number$, rawValue);\r\n" " unknownFields.MergeVarintField($number$, (ulong) rawValue);\r\n"
"} else {\r\n" "} else {\r\n"
" Add$capitalized_name$(value);\r\n" " Add$capitalized_name$(value);\r\n"
"}\r\n"); "}\r\n");
...@@ -244,7 +244,7 @@ void RepeatedEnumFieldGenerator:: ...@@ -244,7 +244,7 @@ void RepeatedEnumFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const { GenerateSerializationCode(io::Printer* printer) const {
printer->Print(variables_, printer->Print(variables_,
"foreach ($type$ element in $capitalized_name$List) {\r\n" "foreach ($type$ element in $capitalized_name$List) {\r\n"
" output.WriteEnum($number$, element.Number);\r\n" " output.WriteEnum($number$, (int) element);\r\n"
"}\r\n"); "}\r\n");
} }
...@@ -253,7 +253,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const { ...@@ -253,7 +253,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_, printer->Print(variables_,
"foreach ($type$ element in $capitalized_name$List) {\r\n" "foreach ($type$ element in $capitalized_name$List) {\r\n"
" size += pb::CodedOutputStream\r\n" " size += pb::CodedOutputStream\r\n"
" .ComputeEnumSize($number$, element.Number);\r\n" " .ComputeEnumSize($number$, (int) element);\r\n"
"}\r\n"); "}\r\n");
} }
......
...@@ -36,7 +36,7 @@ ExtensionGenerator::~ExtensionGenerator() {} ...@@ -36,7 +36,7 @@ ExtensionGenerator::~ExtensionGenerator() {}
void ExtensionGenerator::Generate(io::Printer* printer) { void ExtensionGenerator::Generate(io::Printer* printer) {
map<string, string> vars; map<string, string> vars;
vars["name"] = UnderscoresToCamelCase(descriptor_); vars["name"] = UnderscoresToCapitalizedCamelCase(descriptor_);
vars["containing_type"] = ClassName(descriptor_->containing_type()); vars["containing_type"] = ClassName(descriptor_->containing_type());
vars["index"] = SimpleItoa(descriptor_->index()); vars["index"] = SimpleItoa(descriptor_->index());
...@@ -56,23 +56,13 @@ void ExtensionGenerator::Generate(io::Printer* printer) { ...@@ -56,23 +56,13 @@ void ExtensionGenerator::Generate(io::Printer* printer) {
if (descriptor_->is_repeated()) { if (descriptor_->is_repeated()) {
printer->Print(vars, printer->Print(vars,
"public static final\r\n" "public static readonly\r\n"
" pb::GeneratedMessage.GeneratedExtension<\r\n" " pb::GeneratedExtension<$containing_type$, scg::IList<$type$>> name =\r\n"
" $containing_type$,\r\n" " pb::GeneratedExtension.CreateRepeatedExtension<$containing_type$, $type$>(Descriptor.Extensions[$index$]);\r\n");
" java.util.List<$type$>> $name$ =\r\n"
" pb::GeneratedMessage\r\n"
" .newRepeatedGeneratedExtension(\r\n"
" getDescriptor().getExtensions().get($index$),\r\n"
" typeof ($type$));\r\n");
} else { } else {
printer->Print(vars, printer->Print(vars,
"public static final\r\n" "public static readonly pb::GeneratedExtension<$containing_type$, $type$> $name$ =\r\n"
" pb::GeneratedMessage.GeneratedExtension<\r\n" " pb::GeneratedExtension.CreateExtension<$containing_type$, $type$>(Descriptor.Extensions[$index$]);\r\n");
" $containing_type$,\r\n"
" $type$> $name$ =\r\n"
" pb::GeneratedMessage.newGeneratedExtension(\r\n"
" getDescriptor().getExtensions().get($index$),\r\n"
" typeof ($type$));\r\n");
} }
} }
......
...@@ -148,7 +148,7 @@ void FileGenerator::Generate(io::Printer* printer) { ...@@ -148,7 +148,7 @@ void FileGenerator::Generate(io::Printer* printer) {
printer->Print("\r\n}, new pbd::FileDescriptor[] {\r\n"); printer->Print("\r\n}, new pbd::FileDescriptor[] {\r\n");
for (int i = 0; i < file_->dependency_count(); i++) { for (int i = 0; i < file_->dependency_count(); i++) {
printer->Print( printer->Print(
" $dependency$.getDescriptor(),\r\n", " $dependency$.Descriptor,\r\n",
"dependency", ClassName(file_->dependency(i))); "dependency", ClassName(file_->dependency(i)));
} }
...@@ -165,9 +165,11 @@ void FileGenerator::Generate(io::Printer* printer) { ...@@ -165,9 +165,11 @@ void FileGenerator::Generate(io::Printer* printer) {
// Extensions must be generated in the outer class since they are values, // Extensions must be generated in the outer class since they are values,
// not classes. // not classes.
printer->Print("#region Extensions\r\n"); printer->Print("#region Extensions\r\n");
printer->Print("/*");
for (int i = 0; i < file_->extension_count(); i++) { for (int i = 0; i < file_->extension_count(); i++) {
ExtensionGenerator(file_->extension(i)).Generate(printer); ExtensionGenerator(file_->extension(i)).Generate(printer);
} }
printer->Print("*/\r\n");
printer->Print("#endregion\r\n\r\n"); printer->Print("#endregion\r\n\r\n");
printer->Print("#region Static variables\r\n"); printer->Print("#region Static variables\r\n");
......
...@@ -91,6 +91,10 @@ string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field) { ...@@ -91,6 +91,10 @@ string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field) {
return UnderscoresToCamelCaseImpl(FieldName(field), true); return UnderscoresToCamelCaseImpl(FieldName(field), true);
} }
string UnderscoresToCapitalizedCamelCase(const MethodDescriptor* method) {
return UnderscoresToCamelCaseImpl(method->name(), true);
}
string UnderscoresToCamelCase(const MethodDescriptor* method) { string UnderscoresToCamelCase(const MethodDescriptor* method) {
return UnderscoresToCamelCaseImpl(method->name(), false); return UnderscoresToCamelCaseImpl(method->name(), false);
} }
...@@ -162,19 +166,23 @@ string ClassName(const FileDescriptor* descriptor) { ...@@ -162,19 +166,23 @@ string ClassName(const FileDescriptor* descriptor) {
MappedType GetMappedType(FieldDescriptor::Type field_type) { MappedType GetMappedType(FieldDescriptor::Type field_type) {
switch (field_type) { switch (field_type) {
case FieldDescriptor::TYPE_INT32: case FieldDescriptor::TYPE_INT32:
case FieldDescriptor::TYPE_UINT32:
case FieldDescriptor::TYPE_SINT32: case FieldDescriptor::TYPE_SINT32:
case FieldDescriptor::TYPE_FIXED32:
case FieldDescriptor::TYPE_SFIXED32: case FieldDescriptor::TYPE_SFIXED32:
return MAPPEDTYPE_INT; return MAPPEDTYPE_INT;
case FieldDescriptor::TYPE_INT64: case FieldDescriptor::TYPE_INT64:
case FieldDescriptor::TYPE_UINT64:
case FieldDescriptor::TYPE_SINT64: case FieldDescriptor::TYPE_SINT64:
case FieldDescriptor::TYPE_FIXED64:
case FieldDescriptor::TYPE_SFIXED64: case FieldDescriptor::TYPE_SFIXED64:
return MAPPEDTYPE_LONG; return MAPPEDTYPE_LONG;
case FieldDescriptor::TYPE_UINT32:
case FieldDescriptor::TYPE_FIXED32:
return MAPPEDTYPE_UINT;
case FieldDescriptor::TYPE_UINT64:
case FieldDescriptor::TYPE_FIXED64:
return MAPPEDTYPE_ULONG;
case FieldDescriptor::TYPE_FLOAT: case FieldDescriptor::TYPE_FLOAT:
return MAPPEDTYPE_FLOAT; return MAPPEDTYPE_FLOAT;
......
...@@ -43,6 +43,7 @@ string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field); ...@@ -43,6 +43,7 @@ string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field);
// Similar, but for method names. (Typically, this merely has the effect // Similar, but for method names. (Typically, this merely has the effect
// of lower-casing the first letter of the name.) // of lower-casing the first letter of the name.)
string UnderscoresToCamelCase(const MethodDescriptor* method); string UnderscoresToCamelCase(const MethodDescriptor* method);
string UnderscoresToCapitalizedCamelCase(const MethodDescriptor* method);
// Strips ".proto" or ".protodevel" from the end of a filename. // Strips ".proto" or ".protodevel" from the end of a filename.
string StripProto(const string& filename); string StripProto(const string& filename);
......
...@@ -204,7 +204,7 @@ void MessageGenerator::Generate(io::Printer* printer) { ...@@ -204,7 +204,7 @@ void MessageGenerator::Generate(io::Printer* printer) {
if (descriptor_->extension_range_count() > 0) { if (descriptor_->extension_range_count() > 0) {
printer->Print( printer->Print(
"$access$ sealed partial class $classname$ : pb::GeneratedMessage.ExtendableMessage<$classname$> {\r\n", "$access$ sealed partial class $classname$ : pb::ExtendableMessage<$classname$, $classname$.Builder> {\r\n",
"classname", descriptor_->name(), "classname", descriptor_->name(),
"access", ClassAccessLevel(descriptor_->file())); "access", ClassAccessLevel(descriptor_->file()));
} else { } else {
...@@ -233,7 +233,7 @@ void MessageGenerator::Generate(io::Printer* printer) { ...@@ -233,7 +233,7 @@ void MessageGenerator::Generate(io::Printer* printer) {
" get { return $fileclass$.internal__$identifier$__Descriptor; }\r\n" " get { return $fileclass$.internal__$identifier$__Descriptor; }\r\n"
"}\r\n" "}\r\n"
"\r\n" "\r\n"
"protected internal override pb::FieldAccess.FieldAccessorTable InternalFieldAccessors {\r\n" "protected override pb::FieldAccess.FieldAccessorTable InternalFieldAccessors {\r\n"
" get { return $fileclass$.internal__$identifier$__FieldAccessorTable; }\r\n" " get { return $fileclass$.internal__$identifier$__FieldAccessorTable; }\r\n"
"}\r\n" "}\r\n"
"\r\n", "\r\n",
...@@ -298,7 +298,8 @@ GenerateMessageSerializationMethods(io::Printer* printer) { ...@@ -298,7 +298,8 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
if (descriptor_->extension_range_count() > 0) { if (descriptor_->extension_range_count() > 0) {
printer->Print( printer->Print(
"pb::GeneratedMessage.ExtendableMessage.ExtensionWriter extensionWriter = CreateExtensionWriter();\r\n"); "pb::ExtendableMessage<$classname$, $classname$.Builder>.ExtensionWriter extensionWriter = CreateExtensionWriter(this);\r\n",
"classname", descriptor_->name());
} }
// Merge the fields and the extension ranges, both sorted by field number. // Merge the fields and the extension ranges, both sorted by field number.
...@@ -434,8 +435,7 @@ void MessageGenerator::GenerateBuilder(io::Printer* printer) { ...@@ -434,8 +435,7 @@ void MessageGenerator::GenerateBuilder(io::Printer* printer) {
if (descriptor_->extension_range_count() > 0) { if (descriptor_->extension_range_count() > 0) {
printer->Print( printer->Print(
"$access$ sealed partial class Builder : pb::GeneratedMessage.ExtendableBuilder<\r\n" "$access$ sealed partial class Builder : pb::GeneratedBuilder<$classname$, $classname$.Builder>.ExtendableBuilder {\r\n",
" $classname$, Builder> {\r\n",
"classname", ClassName(descriptor_), "classname", ClassName(descriptor_),
"access", ClassAccessLevel(descriptor_->file())); "access", ClassAccessLevel(descriptor_->file()));
} else { } else {
...@@ -673,7 +673,7 @@ void MessageGenerator::GenerateIsInitialized(io::Printer* printer) { ...@@ -673,7 +673,7 @@ void MessageGenerator::GenerateIsInitialized(io::Printer* printer) {
if (descriptor_->extension_range_count() > 0) { if (descriptor_->extension_range_count() > 0) {
printer->Print( printer->Print(
"if (!extensionsAreInitialized()) return false;\r\n"); "if (!ExtensionsAreInitialized) return false;\r\n");
} }
printer->Outdent(); printer->Outdent();
......
...@@ -36,11 +36,8 @@ ServiceGenerator::ServiceGenerator(const ServiceDescriptor* descriptor) ...@@ -36,11 +36,8 @@ ServiceGenerator::ServiceGenerator(const ServiceDescriptor* descriptor)
ServiceGenerator::~ServiceGenerator() {} ServiceGenerator::~ServiceGenerator() {}
void ServiceGenerator::Generate(io::Printer* printer) { void ServiceGenerator::Generate(io::Printer* printer) {
bool is_own_file = descriptor_->file()->options().csharp_multiple_files();
printer->Print( printer->Print(
"public $static$ abstract class $classname$\r\n" "public abstract class $classname$ : pb::IService {\r\n",
" implements pb::Service {\r\n",
"static", is_own_file ? "" : "static",
"classname", descriptor_->name()); "classname", descriptor_->name());
printer->Indent(); printer->Indent();
...@@ -48,27 +45,24 @@ void ServiceGenerator::Generate(io::Printer* printer) { ...@@ -48,27 +45,24 @@ void ServiceGenerator::Generate(io::Printer* printer) {
for (int i = 0; i < descriptor_->method_count(); i++) { for (int i = 0; i < descriptor_->method_count(); i++) {
const MethodDescriptor* method = descriptor_->method(i); const MethodDescriptor* method = descriptor_->method(i);
map<string, string> vars; map<string, string> vars;
vars["name"] = UnderscoresToCamelCase(method); vars["name"] = UnderscoresToCapitalizedCamelCase(method);
vars["input"] = ClassName(method->input_type()); vars["input"] = ClassName(method->input_type());
vars["output"] = ClassName(method->output_type()); vars["output"] = ClassName(method->output_type());
printer->Print(vars, printer->Print(vars,
"public abstract void $name$(\r\n" "public abstract void $name$(\r\n"
" pb::RpcController controller,\r\n" " pb::IRpcController controller,\r\n"
" $input$ request,\r\n" " $input$ request,\r\n"
" pb::RpcCallback<$output$> done);\r\n"); " global::System.Action<$output$> done);\r\n");
} }
// Generate getDescriptor() and getDescriptorForType(). // Generate Descriptor and DescriptorForType.
printer->Print( printer->Print(
"\r\n" "\r\n"
"public static final\r\n" "public static pbd::ServiceDescriptor Descriptor {\r\n"
" pbd::ServiceDescriptor\r\n" " get { return $file$.Descriptor.Services[$index$]; }\r\n"
" getDescriptor() {\r\n"
" return $file$.getDescriptor().getServices().get($index$);\r\n"
"}\r\n" "}\r\n"
"public final pbd::ServiceDescriptor\r\n" "public pbd::ServiceDescriptor DescriptorForType {\r\n"
" DescriptorForType {\r\n" " get { return Descriptor; }\r\n"
" return getDescriptor();\r\n"
"}\r\n", "}\r\n",
"file", ClassName(descriptor_->file()), "file", ClassName(descriptor_->file()),
"index", SimpleItoa(descriptor_->index())); "index", SimpleItoa(descriptor_->index()));
...@@ -86,18 +80,17 @@ void ServiceGenerator::Generate(io::Printer* printer) { ...@@ -86,18 +80,17 @@ void ServiceGenerator::Generate(io::Printer* printer) {
void ServiceGenerator::GenerateCallMethod(io::Printer* printer) { void ServiceGenerator::GenerateCallMethod(io::Printer* printer) {
printer->Print( printer->Print(
"\r\n" "\r\n"
"public final void callMethod(\r\n" "public void CallMethod(\r\n"
" pbd::MethodDescriptor method,\r\n" " pbd::MethodDescriptor method,\r\n"
" pb::RpcController controller,\r\n" " pb::IRpcController controller,\r\n"
" pb::IMessage request,\r\n" " pb::IMessage request,\r\n"
" pb::RpcCallback<\r\n" " global::System.Action<pb::IMessage> done) {\r\n"
" pb::Message> done) {\r\n" " if (method.Service != Descriptor) {\r\n"
" if (method.getService() != getDescriptor()) {\r\n"
" throw new global::System.ArgumentException(\r\n" " throw new global::System.ArgumentException(\r\n"
" \"Service.CallMethod() given method descriptor for wrong \" +\r\n" " \"Service.CallMethod() given method descriptor for wrong \" +\r\n"
" \"service type.\");\r\n" " \"service type.\");\r\n"
" }\r\n" " }\r\n"
" switch(method.getIndex()) {\r\n"); " switch(method.Index) {\r\n");
printer->Indent(); printer->Indent();
printer->Indent(); printer->Indent();
...@@ -105,13 +98,13 @@ void ServiceGenerator::GenerateCallMethod(io::Printer* printer) { ...@@ -105,13 +98,13 @@ void ServiceGenerator::GenerateCallMethod(io::Printer* printer) {
const MethodDescriptor* method = descriptor_->method(i); const MethodDescriptor* method = descriptor_->method(i);
map<string, string> vars; map<string, string> vars;
vars["index"] = SimpleItoa(i); vars["index"] = SimpleItoa(i);
vars["method"] = UnderscoresToCamelCase(method); vars["method"] = UnderscoresToCapitalizedCamelCase(method);
vars["input"] = ClassName(method->input_type()); vars["input"] = ClassName(method->input_type());
vars["output"] = ClassName(method->output_type()); vars["output"] = ClassName(method->output_type());
printer->Print(vars, printer->Print(vars,
"case $index$:\r\n" "case $index$:\r\n"
" this.$method$(controller, ($input$)request,\r\n" " this.$method$(controller, ($input$)request,\r\n"
" pb::RpcUtil.<$output$>specializeCallback(\r\n" " pb::RpcUtil.SpecializeCallback<$output$>(\r\n"
" done));\r\n" " done));\r\n"
" return;\r\n"); " return;\r\n");
} }
...@@ -132,10 +125,8 @@ void ServiceGenerator::GenerateCallMethod(io::Printer* printer) { ...@@ -132,10 +125,8 @@ void ServiceGenerator::GenerateCallMethod(io::Printer* printer) {
void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which, void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which,
io::Printer* printer) { io::Printer* printer) {
printer->Print( printer->Print(
"public final pb::Message\r\n" "public pb::IMessage Get$request_or_response$Prototype(pbd::MethodDescriptor method) {\r\n"
" Get$request_or_response$Prototype(\r\n" " if (method.Service != Descriptor) {\r\n"
" pbd::MethodDescriptor method) {\r\n"
" if (method.getService() != getDescriptor()) {\r\n"
" throw new global::System.ArgumentException(\r\n" " throw new global::System.ArgumentException(\r\n"
" \"Service.Get$request_or_response$Prototype() given method \" +\r\n" " \"Service.Get$request_or_response$Prototype() given method \" +\r\n"
" \"descriptor for wrong service type.\");\r\n" " \"descriptor for wrong service type.\");\r\n"
...@@ -162,7 +153,6 @@ void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which, ...@@ -162,7 +153,6 @@ void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which,
printer->Outdent(); printer->Outdent();
printer->Outdent(); printer->Outdent();
printer->Print( printer->Print(
" }\r\n" " }\r\n"
"}\r\n" "}\r\n"
...@@ -171,48 +161,45 @@ void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which, ...@@ -171,48 +161,45 @@ void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which,
void ServiceGenerator::GenerateStub(io::Printer* printer) { void ServiceGenerator::GenerateStub(io::Printer* printer) {
printer->Print( printer->Print(
"public static Stub newStub(\r\n" "public static Stub CreateStub(\r\n"
" pb::RpcChannel channel) {\r\n" " pb::IRpcChannel channel) {\r\n"
" return new Stub(channel);\r\n" " return new Stub(channel);\r\n"
"}\r\n" "}\r\n"
"\r\n" "\r\n"
"public static final class Stub extends $classname$ {\r\n", "public class Stub : $classname$ {\r\n",
"classname", ClassName(descriptor_)); "classname", ClassName(descriptor_));
printer->Indent(); printer->Indent();
printer->Print( printer->Print(
"private Stub(pb::RpcChannel channel) {\r\n" "internal Stub(pb::IRpcChannel channel) {\r\n"
" this.channel = channel;\r\n" " this.channel = channel;\r\n"
"}\r\n" "}\r\n"
"\r\n" "\r\n"
"private final pb::RpcChannel channel;\r\n" "private readonly pb::IRpcChannel channel;\r\n"
"\r\n" "\r\n"
"public pb::RpcChannel getChannel() {\r\n" "public pb::IRpcChannel Channel {\r\n"
" return channel;\r\n" " get { return channel; }\r\n"
"}\r\n"); "}\r\n");
for (int i = 0; i < descriptor_->method_count(); i++) { for (int i = 0; i < descriptor_->method_count(); i++) {
const MethodDescriptor* method = descriptor_->method(i); const MethodDescriptor* method = descriptor_->method(i);
map<string, string> vars; map<string, string> vars;
vars["index"] = SimpleItoa(i); vars["index"] = SimpleItoa(i);
vars["method"] = UnderscoresToCamelCase(method); vars["method"] = UnderscoresToCapitalizedCamelCase(method);
vars["input"] = ClassName(method->input_type()); vars["input"] = ClassName(method->input_type());
vars["output"] = ClassName(method->output_type()); vars["output"] = ClassName(method->output_type());
printer->Print(vars, printer->Print(vars,
"\r\n" "\r\n"
"public void $method$(\r\n" "public override void $method$(\r\n"
" pb::RpcController controller,\r\n" " pb::IRpcController controller,\r\n"
" $input$ request,\r\n" " $input$ request,\r\n"
" pb::RpcCallback<$output$> done) {\r\n" " global::System.Action<$output$> done) {\r\n"
" channel.callMethod(\r\n" " channel.CallMethod(\r\n"
" Descriptor.Methods[$index$],\r\n" " Descriptor.Methods[$index$],\r\n"
" controller,\r\n" " controller,\r\n"
" request,\r\n" " request,\r\n"
" $output$.DefaultInstance,\r\n" " $output$.DefaultInstance,\r\n"
" pb::RpcUtil.generalizeCallback(\r\n" " pb::RpcUtil.GeneralizeCallback(done, $output$.DefaultInstance));\r\n"
" done,\r\n"
" typeof ($output$),\r\n"
" $output$.DefaultInstance));\r\n"
"}\r\n"); "}\r\n");
} }
......
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
// //
// A proto file we will use for unit testing. // A proto file we will use for unit testing.
option csharp_namespace = "Google.ProtocolBuffers.TestProtos";
option csharp_file_classname = "UnitTestProtoFile";
import "google/protobuf/unittest_import.proto"; import "google/protobuf/unittest_import.proto";
......
...@@ -24,6 +24,9 @@ import "google/protobuf/unittest_optimize_for.proto"; ...@@ -24,6 +24,9 @@ import "google/protobuf/unittest_optimize_for.proto";
package protobuf_unittest; package protobuf_unittest;
option csharp_namespace = "Google.ProtocolBuffers.TestProtos";
option csharp_file_classname = "UnitTestEmbedOptimizeForProtoFile";
// We optimize for speed here, but we are importing a proto that is optimized // We optimize for speed here, but we are importing a proto that is optimized
// for code size. // for code size.
option optimize_for = SPEED; option optimize_for = SPEED;
......
...@@ -29,9 +29,12 @@ package protobuf_unittest_import; ...@@ -29,9 +29,12 @@ package protobuf_unittest_import;
option optimize_for = SPEED; option optimize_for = SPEED;
// Excercise the java_package option. // Exercise the java_package option.
option java_package = "com.google.protobuf.test"; option java_package = "com.google.protobuf.test";
option csharp_namespace = "Google.ProtocolBuffers.TestProtos";
option csharp_file_classname = "UnitTestImportProtoFile";
// Do not set a java_outer_classname here to verify that Proto2 works without // Do not set a java_outer_classname here to verify that Proto2 works without
// one. // one.
......
...@@ -24,6 +24,9 @@ package protobuf_unittest; ...@@ -24,6 +24,9 @@ package protobuf_unittest;
option optimize_for = SPEED; option optimize_for = SPEED;
option csharp_namespace = "Google.ProtocolBuffers.TestProtos";
option csharp_file_classname = "UnitTestMessageSetProtoFile";
// A message with message_set_wire_format. // A message with message_set_wire_format.
message TestMessageSet { message TestMessageSet {
option message_set_wire_format = true; option message_set_wire_format = true;
......
...@@ -26,6 +26,9 @@ package protobuf_unittest; ...@@ -26,6 +26,9 @@ package protobuf_unittest;
option optimize_for = CODE_SIZE; option optimize_for = CODE_SIZE;
option csharp_namespace = "Google.ProtocolBuffers.TestProtos";
option csharp_file_classname = "UnitTestOptimizeForProtoFile";
message TestOptimizedForSize { message TestOptimizedForSize {
optional int32 i = 1; optional int32 i = 1;
optional ForeignMessage msg = 19; optional ForeignMessage msg = 19;
......
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