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

Autogeneration now hopefully close to correct. Library builds! (Not finished though...)

parent de21d2c9
...@@ -43,7 +43,8 @@ Google.ProtocolBuffers.dll_sources = \ ...@@ -43,7 +43,8 @@ Google.ProtocolBuffers.dll_sources = \
Google.ProtocolBuffers.dll: $(Google.ProtocolBuffers.dll_sources) Google.ProtocolBuffers.dll: $(Google.ProtocolBuffers.dll_sources)
cp $(srcdir)/ProtocolBuffers/Properties/Google.ProtocolBuffers.snk . cp $(srcdir)/ProtocolBuffers/Properties/Google.ProtocolBuffers.snk .
gmcs -codepage:utf8 -debug -target:library -out:Google.ProtocolBuffers.dll $(Google.ProtocolBuffers.dll_sources) gmcs -codepage:utf8 -debug -target:library -out:Google.ProtocolBuffers.dll \
$(Google.ProtocolBuffers.dll_sources) -keyfile Google.ProtocolBuffers.snk
install-data-local: Google.ProtocolBuffers.dll install-data-local: Google.ProtocolBuffers.dll
gacutil -i Google.ProtocolBuffers.dll -package google gacutil -i Google.ProtocolBuffers.dll -package google
......
...@@ -25,7 +25,6 @@ namespace Google.ProtocolBuffers { ...@@ -25,7 +25,6 @@ namespace Google.ProtocolBuffers {
protected abstract IMessage BuildPartialImpl(); protected abstract IMessage BuildPartialImpl();
protected abstract IBuilder CloneImpl(); protected abstract IBuilder CloneImpl();
protected abstract IMessage DefaultInstanceForTypeImpl { get; } protected abstract IMessage DefaultInstanceForTypeImpl { get; }
protected abstract IBuilder CreateBuilderForFieldImpl(FieldDescriptor field);
protected abstract IBuilder ClearFieldImpl(FieldDescriptor field); protected abstract IBuilder ClearFieldImpl(FieldDescriptor field);
protected abstract IBuilder AddRepeatedFieldImpl(FieldDescriptor field, object value); protected abstract IBuilder AddRepeatedFieldImpl(FieldDescriptor field, object value);
#endregion #endregion
...@@ -47,9 +46,7 @@ namespace Google.ProtocolBuffers { ...@@ -47,9 +46,7 @@ namespace Google.ProtocolBuffers {
get { return DefaultInstanceForTypeImpl; } get { return DefaultInstanceForTypeImpl; }
} }
IBuilder IBuilder.CreateBuilderForField(FieldDescriptor field) { public abstract IBuilder CreateBuilderForField(FieldDescriptor field);
return CreateBuilderForFieldImpl(field);
}
IBuilder IBuilder.ClearField(FieldDescriptor field) { IBuilder IBuilder.ClearField(FieldDescriptor field) {
return ClearFieldImpl(field); return ClearFieldImpl(field);
...@@ -67,7 +64,7 @@ namespace Google.ProtocolBuffers { ...@@ -67,7 +64,7 @@ namespace Google.ProtocolBuffers {
return this; return this;
} }
public IBuilder MergeFrom(IMessage other) { public virtual IBuilder MergeFrom(IMessage other) {
if (other.DescriptorForType != DescriptorForType) { if (other.DescriptorForType != DescriptorForType) {
throw new ArgumentException("MergeFrom(Message) can only merge messages of the same type."); throw new ArgumentException("MergeFrom(Message) can only merge messages of the same type.");
} }
...@@ -106,18 +103,18 @@ namespace Google.ProtocolBuffers { ...@@ -106,18 +103,18 @@ namespace Google.ProtocolBuffers {
return this; return this;
} }
public IBuilder MergeFrom(CodedInputStream input) { IBuilder IBuilder.MergeFrom(CodedInputStream input) {
return MergeFrom(input, ExtensionRegistry.Empty); return ((IBuilder)this).MergeFrom(input, ExtensionRegistry.Empty);
} }
public IBuilder MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry) { IBuilder IBuilder.MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry) {
UnknownFieldSet.Builder unknownFields = UnknownFieldSet.CreateBuilder(UnknownFields); UnknownFieldSet.Builder unknownFields = UnknownFieldSet.CreateBuilder(UnknownFields);
FieldSet.MergeFrom(input, unknownFields, extensionRegistry, this); FieldSet.MergeFrom(input, unknownFields, extensionRegistry, this);
UnknownFields = unknownFields.Build(); UnknownFields = unknownFields.Build();
return this; return this;
} }
public IBuilder MergeUnknownFields(UnknownFieldSet unknownFields) { IBuilder IBuilder.MergeUnknownFields(UnknownFieldSet unknownFields) {
UnknownFields = UnknownFieldSet.CreateBuilder(UnknownFields) UnknownFields = UnknownFieldSet.CreateBuilder(UnknownFields)
.MergeFrom(unknownFields) .MergeFrom(unknownFields)
.Build(); .Build();
...@@ -126,44 +123,44 @@ namespace Google.ProtocolBuffers { ...@@ -126,44 +123,44 @@ namespace Google.ProtocolBuffers {
public UnknownFieldSet UnknownFields { get; set; } public UnknownFieldSet UnknownFields { get; set; }
public IBuilder MergeFrom(ByteString data) { IBuilder IBuilder.MergeFrom(ByteString data) {
CodedInputStream input = data.CreateCodedInput(); CodedInputStream input = data.CreateCodedInput();
MergeFrom(input); ((IBuilder)this).MergeFrom(input);
input.CheckLastTagWas(0); input.CheckLastTagWas(0);
return this; return this;
} }
public IBuilder MergeFrom(ByteString data, ExtensionRegistry extensionRegistry) { IBuilder IBuilder.MergeFrom(ByteString data, ExtensionRegistry extensionRegistry) {
CodedInputStream input = data.CreateCodedInput(); CodedInputStream input = data.CreateCodedInput();
MergeFrom(input, extensionRegistry); ((IBuilder)this).MergeFrom(input, extensionRegistry);
input.CheckLastTagWas(0); input.CheckLastTagWas(0);
return this; return this;
} }
public IBuilder MergeFrom(byte[] data) { IBuilder IBuilder.MergeFrom(byte[] data) {
CodedInputStream input = CodedInputStream.CreateInstance(data); CodedInputStream input = CodedInputStream.CreateInstance(data);
MergeFrom(input); ((IBuilder)this).MergeFrom(input);
input.CheckLastTagWas(0); input.CheckLastTagWas(0);
return this; return this;
} }
public IBuilder MergeFrom(byte[] data, ExtensionRegistry extensionRegistry) { IBuilder IBuilder.MergeFrom(byte[] data, ExtensionRegistry extensionRegistry) {
CodedInputStream input = CodedInputStream.CreateInstance(data); CodedInputStream input = CodedInputStream.CreateInstance(data);
MergeFrom(input, extensionRegistry); ((IBuilder)this).MergeFrom(input, extensionRegistry);
input.CheckLastTagWas(0); input.CheckLastTagWas(0);
return this; return this;
} }
public IBuilder MergeFrom(Stream input) { IBuilder IBuilder.MergeFrom(Stream input) {
CodedInputStream codedInput = CodedInputStream.CreateInstance(input); CodedInputStream codedInput = CodedInputStream.CreateInstance(input);
MergeFrom(codedInput); ((IBuilder)this).MergeFrom(codedInput);
codedInput.CheckLastTagWas(0); codedInput.CheckLastTagWas(0);
return this; return this;
} }
public IBuilder MergeFrom(Stream input, ExtensionRegistry extensionRegistry) { IBuilder IBuilder.MergeFrom(Stream input, ExtensionRegistry extensionRegistry) {
CodedInputStream codedInput = CodedInputStream.CreateInstance(input); CodedInputStream codedInput = CodedInputStream.CreateInstance(input);
MergeFrom(codedInput, extensionRegistry); ((IBuilder) this).MergeFrom(codedInput, extensionRegistry);
codedInput.CheckLastTagWas(0); codedInput.CheckLastTagWas(0);
return this; return this;
} }
......
...@@ -13,11 +13,9 @@ ...@@ -13,11 +13,9 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text;
using Google.ProtocolBuffers.Descriptors; using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers { namespace Google.ProtocolBuffers {
...@@ -56,7 +54,7 @@ namespace Google.ProtocolBuffers { ...@@ -56,7 +54,7 @@ namespace Google.ProtocolBuffers {
} }
#endregion #endregion
public bool IsInitialized { public virtual bool IsInitialized {
get { get {
// Check that all required fields are present. // Check that all required fields are present.
foreach (FieldDescriptor field in DescriptorForType.Fields) { foreach (FieldDescriptor field in DescriptorForType.Fields) {
...@@ -92,7 +90,7 @@ namespace Google.ProtocolBuffers { ...@@ -92,7 +90,7 @@ namespace Google.ProtocolBuffers {
return TextFormat.PrintToString(this); return TextFormat.PrintToString(this);
} }
public void WriteTo(CodedOutputStream output) { public virtual void WriteTo(CodedOutputStream output) {
foreach (KeyValuePair<FieldDescriptor, object> entry in AllFields) { foreach (KeyValuePair<FieldDescriptor, object> entry in AllFields) {
FieldDescriptor field = entry.Key; FieldDescriptor field = entry.Key;
if (field.IsRepeated) { if (field.IsRepeated) {
...@@ -107,14 +105,14 @@ namespace Google.ProtocolBuffers { ...@@ -107,14 +105,14 @@ namespace Google.ProtocolBuffers {
} }
UnknownFieldSet unknownFields = UnknownFields; UnknownFieldSet unknownFields = UnknownFields;
if (DescriptorForType.Options.IsMessageSetWireFormat) { if (DescriptorForType.Options.MessageSetWireFormat) {
unknownFields.WriteAsMessageSetTo(output); unknownFields.WriteAsMessageSetTo(output);
} else { } else {
unknownFields.WriteTo(output); unknownFields.WriteTo(output);
} }
} }
public int SerializedSize { public virtual int SerializedSize {
get { get {
int size = memoizedSize; int size = memoizedSize;
if (size != -1) { if (size != -1) {
...@@ -134,7 +132,7 @@ namespace Google.ProtocolBuffers { ...@@ -134,7 +132,7 @@ namespace Google.ProtocolBuffers {
} }
UnknownFieldSet unknownFields = UnknownFields; UnknownFieldSet unknownFields = UnknownFields;
if (DescriptorForType.Options.IsMessageSetWireFormat) { if (DescriptorForType.Options.MessageSetWireFormat) {
size += unknownFields.SerializedSizeAsMessageSet; size += unknownFields.SerializedSizeAsMessageSet;
} else { } else {
size += unknownFields.SerializedSize; size += unknownFields.SerializedSize;
...@@ -184,73 +182,5 @@ namespace Google.ProtocolBuffers { ...@@ -184,73 +182,5 @@ namespace Google.ProtocolBuffers {
hash = (53 * hash) + AllFields.GetHashCode(); hash = (53 * hash) + AllFields.GetHashCode();
return hash; return hash;
} }
#region IMessage Members
MessageDescriptor IMessage.DescriptorForType {
get { throw new NotImplementedException(); }
}
IDictionary<FieldDescriptor, object> IMessage.AllFields {
get { throw new NotImplementedException(); }
}
bool IMessage.HasField(FieldDescriptor field) {
throw new NotImplementedException();
}
object IMessage.this[FieldDescriptor field] {
get { throw new NotImplementedException(); }
}
int IMessage.GetRepeatedFieldCount(FieldDescriptor field) {
throw new NotImplementedException();
}
object IMessage.this[FieldDescriptor field, int index] {
get { throw new NotImplementedException(); }
}
UnknownFieldSet IMessage.UnknownFields {
get { throw new NotImplementedException(); }
}
bool IMessage.IsInitialized {
get { throw new NotImplementedException(); }
}
void IMessage.WriteTo(CodedOutputStream output) {
throw new NotImplementedException();
}
int IMessage.SerializedSize {
get { throw new NotImplementedException(); }
}
bool IMessage.Equals(object other) {
throw new NotImplementedException();
}
int IMessage.GetHashCode() {
throw new NotImplementedException();
}
string IMessage.ToString() {
throw new NotImplementedException();
}
ByteString IMessage.ToByteString() {
throw new NotImplementedException();
}
byte[] IMessage.ToByteArray() {
throw new NotImplementedException();
}
void IMessage.WriteTo(Stream output) {
throw new NotImplementedException();
}
#endregion
} }
} }
...@@ -5,6 +5,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos { ...@@ -5,6 +5,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
/// <summary> /// <summary>
/// This only exists until we've got the real code... /// This only exists until we've got the real code...
/// </summary> /// </summary>
/*
public abstract class TemporaryMessage<T> : IMessage<T> where T : IMessage<T> { public abstract class TemporaryMessage<T> : IMessage<T> where T : IMessage<T> {
#region IMessage<T> Members #region IMessage<T> Members
...@@ -84,7 +85,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos { ...@@ -84,7 +85,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
} }
public partial class MessageOptions : TemporaryMessage<MessageOptions> { public partial class MessageOptions : TemporaryMessage<MessageOptions> {
public bool IsMessageSetWireFormat; public bool MessageSetWireFormat;
} }
public partial class DescriptorProto : TemporaryMessage<DescriptorProto> { public partial class DescriptorProto : TemporaryMessage<DescriptorProto> {
...@@ -123,6 +124,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos { ...@@ -123,6 +124,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
public string FullName { get; set; } public string FullName { get; set; }
public FileOptions Options { get; set; } public FileOptions Options { get; set; }
public string Package { get; set; }
} }
public partial class FileOptions : TemporaryMessage<FileOptions> { } public partial class FileOptions : TemporaryMessage<FileOptions> { }
...@@ -143,5 +145,5 @@ namespace Google.ProtocolBuffers.DescriptorProtos { ...@@ -143,5 +145,5 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
} }
public partial class ServiceOptions : TemporaryMessage<ServiceOptions> { } public partial class ServiceOptions : TemporaryMessage<ServiceOptions> { } */
} }
This diff is collapsed.
This diff is collapsed.
...@@ -7,10 +7,6 @@ ...@@ -7,10 +7,6 @@
/// </summary> /// </summary>
/// <typeparam name="TOptions">The associated options protocol buffer type</typeparam> /// <typeparam name="TOptions">The associated options protocol buffer type</typeparam>
public interface IDescriptorProto<TOptions> { public interface IDescriptorProto<TOptions> {
/// <summary>
/// The fully qualified name of the descriptor's target.
/// </summary>
string FullName { get; }
/// <summary> /// <summary>
/// The brief name of the descriptor's target. /// The brief name of the descriptor's target.
......
...@@ -32,9 +32,10 @@ namespace Google.ProtocolBuffers.Descriptors { ...@@ -32,9 +32,10 @@ namespace Google.ProtocolBuffers.Descriptors {
/// <summary> /// <summary>
/// The fully qualified name of the descriptor's target. /// The fully qualified name of the descriptor's target.
/// TODO(jonskeet): Implement!
/// </summary> /// </summary>
public string FullName { public string FullName {
get { return proto.FullName; } get { return null; }
} }
/// <summary> /// <summary>
......
using System.Collections.Generic;
namespace Google.ProtocolBuffers.Descriptors {
/// <summary>
/// Contains lookup tables containing all the descriptors defined in a particular file.
/// </summary>
internal class DescriptorPool {
IDictionary<string, object> byName;
/// <summary>
/// Finds a symbol of the given name within the pool.
/// </summary>
/// <typeparam name="T">The type of symbol to look for</typeparam>
/// <param name="name">Name to look up</param>
/// <returns>The symbol with the given name and type,
/// or null if the symbol doesn't exist or has the wrong type</returns>
internal T FindSymbol<T>(string name) where T : class {
return default(T);
}
}
}
using System;
namespace Google.ProtocolBuffers.Descriptors {
/// <summary>
/// Allows enum values to express the index within their descriptor.
/// </summary>
[AttributeUsage(AttributeTargets.Field)]
internal class EnumDescriptorIndexAttribute : Attribute {
readonly int index;
internal int Index {
get { return index; }
}
internal EnumDescriptorIndexAttribute(int index) {
this.index = index;
}
}
}
using Google.ProtocolBuffers.DescriptorProtos; using System;
using Google.ProtocolBuffers.DescriptorProtos;
using System.Collections.Generic;
namespace Google.ProtocolBuffers.Descriptors { namespace Google.ProtocolBuffers.Descriptors {
public class FileDescriptor : DescriptorBase<FileDescriptorProto, FileOptions> { public class FileDescriptor : DescriptorBase<FileDescriptorProto, FileOptions> {
private readonly IList<MessageDescriptor> messageTypes;
private readonly IList<EnumDescriptor> enumTypes;
private readonly IList<ServiceDescriptor> services;
private readonly IList<FieldDescriptor> extensions;
private readonly IList<FileDescriptor> dependencies;
private readonly DescriptorPool pool;
public FileDescriptor(FileDescriptorProto proto, FileDescriptor file) : base(proto, file) { public FileDescriptor(FileDescriptorProto proto, FileDescriptor file) : base(proto, file) {
} }
/// <summary>
/// The package as declared in the .proto file. This may or may not
/// be equivalent to the .NET namespace of the generated classes.
/// </summary>
public string Package {
get { return Proto.Package; }
}
/// <value>
/// Unmodifiable list of top-level message types declared in this file.
/// </value>
public IList<MessageDescriptor> MessageTypes {
get { return messageTypes; }
}
/// <value>
/// Unmodifiable list of top-level enum types declared in this file.
/// </value>
public IList<EnumDescriptor> EnumTypes {
get { return enumTypes; }
}
/// <value>
/// Unmodifiable list of top-level services declared in this file.
/// </value>
public IList<ServiceDescriptor> Services {
get { return services; }
}
/// <value>
/// Unmodifiable list of top-level extensions declared in this file.
/// </value>
public IList<FieldDescriptor> Extensions {
get { return extensions; }
}
/// <value>
/// Unmodifiable list of this file's dependencies (imports).
/// </value>
public IList<FileDescriptor> Dependencies {
get { return dependencies; }
}
public static FileDescriptor BuildFrom(FileDescriptorProto proto,
FileDescriptor[] dependencies) {
throw new NotImplementedException();
}
/// <summary>
/// This method is to be called by generated code only. It is equivalent
/// to BuilderFrom except that the FileDescriptorProto is encoded in
/// protocol buffer wire format.
/// </summary>
public static FileDescriptor InternalBuildGeneratedFileFrom(byte[] descriptorData,
FileDescriptor[] dependencies) {
FileDescriptorProto proto = FileDescriptorProto.ParseFrom(descriptorData);
return BuildFrom(proto, dependencies);
}
} }
} }
...@@ -16,5 +16,12 @@ namespace Google.ProtocolBuffers.Descriptors { ...@@ -16,5 +16,12 @@ namespace Google.ProtocolBuffers.Descriptors {
internal FieldDescriptor FindFieldByNumber(int fieldNumber) { internal FieldDescriptor FindFieldByNumber(int fieldNumber) {
throw new System.NotImplementedException(); throw new System.NotImplementedException();
} }
/// <value>
/// List of message types nested within this one.
/// </value>
public IList<MessageDescriptor> NestedTypes {
get { throw new System.NotImplementedException(); }
}
} }
} }
...@@ -136,7 +136,7 @@ namespace Google.ProtocolBuffers { ...@@ -136,7 +136,7 @@ namespace Google.ProtocolBuffers {
extension.Descriptor.FieldNumber)] = extension; extension.Descriptor.FieldNumber)] = extension;
FieldDescriptor field = extension.Descriptor; FieldDescriptor field = extension.Descriptor;
if (field.ContainingType.Options.IsMessageSetWireFormat if (field.ContainingType.Options.MessageSetWireFormat
&& field.FieldType == FieldType.Message && field.FieldType == FieldType.Message
&& field.IsOptional && field.IsOptional
&& field.ExtensionScope == field.MessageType) { && field.ExtensionScope == field.MessageType) {
......
...@@ -2,9 +2,7 @@ ...@@ -2,9 +2,7 @@
using Google.ProtocolBuffers.Descriptors; using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers.FieldAccess { namespace Google.ProtocolBuffers.FieldAccess {
public class FieldAccessorTable<TMessage, TBuilder> public class FieldAccessorTable {
where TMessage : IMessage<TMessage>
where TBuilder : IBuilder<TMessage> {
readonly MessageDescriptor descriptor; readonly MessageDescriptor descriptor;
...@@ -12,11 +10,11 @@ namespace Google.ProtocolBuffers.FieldAccess { ...@@ -12,11 +10,11 @@ namespace Google.ProtocolBuffers.FieldAccess {
get { return descriptor; } get { return descriptor; }
} }
public FieldAccessorTable(MessageDescriptor descriptor, String[] pascalCaseNames) { public FieldAccessorTable(MessageDescriptor descriptor, String[] pascalCaseFieldNames, Type messageType, Type builderType) {
this.descriptor = descriptor; this.descriptor = descriptor;
} }
internal IFieldAccessor<TMessage, TBuilder> this[FieldDescriptor field] { internal IFieldAccessor this[FieldDescriptor field] {
get { return null; } get { return null; }
} }
} }
......
...@@ -5,25 +5,23 @@ ...@@ -5,25 +5,23 @@
/// The property descriptors for each field are created once and then cached. /// The property descriptors for each field are created once and then cached.
/// In addition, this interface holds knowledge of repeated fields, builders etc. /// In addition, this interface holds knowledge of repeated fields, builders etc.
/// </summary> /// </summary>
internal interface IFieldAccessor<TMessage, TBuilder> internal interface IFieldAccessor {
where TMessage : IMessage<TMessage>
where TBuilder : IBuilder<TMessage> {
/// <summary> /// <summary>
/// Indicates whether the specified message contains the field. /// Indicates whether the specified message contains the field.
/// </summary> /// </summary>
bool Has(IMessage<TMessage> message); bool Has(IMessage message);
/// <summary> /// <summary>
/// Gets the count of the repeated field in the specified message. /// Gets the count of the repeated field in the specified message.
/// </summary> /// </summary>
int GetRepeatedCount(IMessage<TMessage> message); int GetRepeatedCount(IMessage message);
/// <summary> /// <summary>
/// Clears the field in the specified builder. /// Clears the field in the specified builder.
/// </summary> /// </summary>
/// <param name="builder"></param> /// <param name="builder"></param>
void Clear(IBuilder<TMessage> builder); void Clear(IBuilder builder);
/// <summary> /// <summary>
/// Creates a builder for the type of this field (which must be a message field). /// Creates a builder for the type of this field (which must be a message field).
...@@ -33,27 +31,27 @@ ...@@ -33,27 +31,27 @@
/// <summary> /// <summary>
/// Accessor for single fields /// Accessor for single fields
/// </summary> /// </summary>
object GetValue(IMessage<TMessage> message); object GetValue(IMessage message);
/// <summary> /// <summary>
/// Mutator for single fields /// Mutator for single fields
/// </summary> /// </summary>
void SetValue(IBuilder<TMessage> builder, object value); void SetValue(IBuilder builder, object value);
/// <summary> /// <summary>
/// Accessor for repeated fields /// Accessor for repeated fields
/// </summary> /// </summary>
object GetRepeatedValue(IMessage<TMessage> message, int index); object GetRepeatedValue(IMessage message, int index);
/// <summary> /// <summary>
/// Mutator for repeated fields /// Mutator for repeated fields
/// </summary> /// </summary>
void SetRepeated(IBuilder<TMessage> builder, int index, object value); void SetRepeated(IBuilder builder, int index, object value);
/// <summary> /// <summary>
/// Adds the specified value to the field in the given builder. /// Adds the specified value to the field in the given builder.
/// </summary> /// </summary>
void AddRepeated(IBuilder<TMessage> builder, object value); void AddRepeated(IBuilder builder, object value);
/// <summary> /// <summary>
/// Returns a read-only wrapper around the value of a repeated field. /// Returns a read-only wrapper around the value of a repeated field.
/// </summary> /// </summary>
object GetRepeatedWrapper(IBuilder<TMessage> builder); object GetRepeatedWrapper(IBuilder builder);
} }
} }
...@@ -121,7 +121,7 @@ namespace Google.ProtocolBuffers { ...@@ -121,7 +121,7 @@ namespace Google.ProtocolBuffers {
uint tag) { uint tag) {
MessageDescriptor type = builder.DescriptorForType; MessageDescriptor type = builder.DescriptorForType;
if (type.Options.IsMessageSetWireFormat if (type.Options.MessageSetWireFormat
&& tag == WireFormat.MessageSetTag.ItemStart) { && tag == WireFormat.MessageSetTag.ItemStart) {
MergeMessageSetExtensionFromCodedStream(input, unknownFields, extensionRegistry, builder); MergeMessageSetExtensionFromCodedStream(input, unknownFields, extensionRegistry, builder);
return true; return true;
...@@ -524,7 +524,7 @@ namespace Google.ProtocolBuffers { ...@@ -524,7 +524,7 @@ namespace Google.ProtocolBuffers {
/// Writes a single field to a CodedOutputStream. /// Writes a single field to a CodedOutputStream.
/// </summary> /// </summary>
public void WriteField(FieldDescriptor field, Object value, CodedOutputStream output) { public void WriteField(FieldDescriptor field, Object value, CodedOutputStream output) {
if (field.IsExtension && field.ContainingType.Options.IsMessageSetWireFormat) { if (field.IsExtension && field.ContainingType.Options.MessageSetWireFormat) {
output.WriteMessageSetExtension(field.FieldNumber, (IMessage) value); output.WriteMessageSetExtension(field.FieldNumber, (IMessage) value);
} else { } else {
if (field.IsRepeated) { if (field.IsRepeated) {
...@@ -548,7 +548,7 @@ namespace Google.ProtocolBuffers { ...@@ -548,7 +548,7 @@ namespace Google.ProtocolBuffers {
FieldDescriptor field = entry.Key; FieldDescriptor field = entry.Key;
object value = entry.Value; object value = entry.Value;
if (field.IsExtension && field.ContainingType.Options.IsMessageSetWireFormat) { if (field.IsExtension && field.ContainingType.Options.MessageSetWireFormat) {
size += CodedOutputStream.ComputeMessageSetExtensionSize(field.FieldNumber, (IMessage) value); size += CodedOutputStream.ComputeMessageSetExtensionSize(field.FieldNumber, (IMessage) value);
} else { } else {
if (field.IsRepeated) { if (field.IsRepeated) {
......
...@@ -3,6 +3,7 @@ using System.Collections.Generic; ...@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Text; using System.Text;
using Google.ProtocolBuffers.Collections; using Google.ProtocolBuffers.Collections;
using Google.ProtocolBuffers.Descriptors; using Google.ProtocolBuffers.Descriptors;
using System.IO;
namespace Google.ProtocolBuffers { namespace Google.ProtocolBuffers {
/// <summary> /// <summary>
...@@ -17,7 +18,7 @@ namespace Google.ProtocolBuffers { ...@@ -17,7 +18,7 @@ namespace Google.ProtocolBuffers {
/// <summary> /// <summary>
/// Returns the message being built at the moment. /// Returns the message being built at the moment.
/// </summary> /// </summary>
protected abstract GeneratedMessage<TMessage,TBuilder> MessageBeingBuilt { get; } protected abstract TMessage MessageBeingBuilt { get; }
public override bool Initialized { public override bool Initialized {
get { return MessageBeingBuilt.IsInitialized; } get { return MessageBeingBuilt.IsInitialized; }
...@@ -40,6 +41,29 @@ namespace Google.ProtocolBuffers { ...@@ -40,6 +41,29 @@ namespace Google.ProtocolBuffers {
} }
} }
/// <summary>
/// Adds all of the specified values to the given collection.
/// </summary>
protected void AddRange<T>(IEnumerable<T> source, IList<T> destination) {
List<T> list = destination as List<T>;
if (list != null) {
list.AddRange(source);
} else {
foreach (T element in source) {
destination.Add(element);
}
}
}
/// <summary>
/// Called by derived classes to parse an unknown field.
/// </summary>
/// <returns>true unless the tag is an end-group tag</returns>
protected bool ParseUnknownField(CodedInputStream input, UnknownFieldSet.Builder unknownFields,
ExtensionRegistry extensionRegistry, uint tag) {
return unknownFields.MergeFieldFrom(tag, input);
}
public override MessageDescriptor DescriptorForType { public override MessageDescriptor DescriptorForType {
get { return MessageBeingBuilt.DescriptorForType; } get { return MessageBeingBuilt.DescriptorForType; }
} }
...@@ -73,8 +97,8 @@ namespace Google.ProtocolBuffers { ...@@ -73,8 +97,8 @@ namespace Google.ProtocolBuffers {
get { return DefaultInstanceForType; } get { return DefaultInstanceForType; }
} }
protected override IBuilder CreateBuilderForFieldImpl(FieldDescriptor field) { public override IBuilder CreateBuilderForField(FieldDescriptor field) {
return CreateBuilderForField(field); return MessageBeingBuilt.InternalFieldAccessors[field].CreateBuilder();
} }
protected override IBuilder ClearFieldImpl(FieldDescriptor field) { protected override IBuilder ClearFieldImpl(FieldDescriptor field) {
...@@ -85,69 +109,78 @@ namespace Google.ProtocolBuffers { ...@@ -85,69 +109,78 @@ namespace Google.ProtocolBuffers {
return AddRepeatedField(field, value); return AddRepeatedField(field, value);
} }
public new abstract IBuilder<TMessage> Clear(); public IBuilder<TMessage> ClearField(FieldDescriptor field) {
MessageBeingBuilt.InternalFieldAccessors[field].Clear(this);
public IBuilder<TMessage> MergeFrom(IMessage<TMessage> other) { return this;
throw new NotImplementedException();
} }
public abstract TMessage Build(); // FIXME: Implement!
public virtual IBuilder<TMessage> MergeFrom(TMessage other) { return this; }
public abstract TMessage BuildPartial(); public virtual IBuilder<TMessage> MergeUnknownFields(UnknownFieldSet unknownFields) { return this; }
public abstract IBuilder<TMessage> Clone();
IBuilder<TMessage> IBuilder<TMessage>.MergeFrom(CodedInputStream input) {
throw new NotImplementedException();
}
IBuilder<TMessage> IBuilder<TMessage>.MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry) { public IBuilder<TMessage> AddRepeatedField(FieldDescriptor field, object value) {
throw new NotImplementedException(); MessageBeingBuilt.InternalFieldAccessors[field].AddRepeated(this, value);
return this;
} }
public TMessage DefaultInstanceForType { public IBuilder<TMessage> MergeFrom(ByteString data) {
get { throw new NotImplementedException(); } ((IBuilder) this).MergeFrom(data);
return this;
} }
public IBuilder CreateBuilderForField(FieldDescriptor field) { public IBuilder<TMessage> MergeFrom(ByteString data, ExtensionRegistry extensionRegistry) {
throw new NotImplementedException(); ((IBuilder) this).MergeFrom(data, extensionRegistry);
return this;
} }
public IBuilder<TMessage> ClearField(FieldDescriptor field) { public IBuilder<TMessage> MergeFrom(byte[] data) {
MessageBeingBuilt.InternalFieldAccessors[field].Clear(this); ((IBuilder) this).MergeFrom(data);
return this; return this;
} }
public IBuilder<TMessage> AddRepeatedField(FieldDescriptor field, object value) { public IBuilder<TMessage> MergeFrom(byte[] data, ExtensionRegistry extensionRegistry) {
((IBuilder) this).MergeFrom(data, extensionRegistry);
return this; return this;
} }
public new IBuilder<TMessage> MergeUnknownFields(UnknownFieldSet unknownFields) { public IBuilder<TMessage> MergeFrom(Stream input) {
throw new NotImplementedException(); ((IBuilder) this).MergeFrom(input);
return this;
} }
IBuilder<TMessage> IBuilder<TMessage>.MergeFrom(ByteString data) { public IBuilder<TMessage> MergeFrom(Stream input, ExtensionRegistry extensionRegistry) {
throw new NotImplementedException(); ((IBuilder) this).MergeFrom(input, extensionRegistry);
return this;
} }
IBuilder<TMessage> IBuilder<TMessage>.MergeFrom(ByteString data, ExtensionRegistry extensionRegistry) { /// <summary>
throw new NotImplementedException(); /// Like Build(), but will wrap UninitializedMessageException in
/// InvalidProtocolBufferException.
/// TODO(jonskeet): This used to be generated for each class. Find out why.
/// </summary>
public TMessage BuildParsed() {
if (!Initialized) {
throw new UninitializedMessageException(MessageBeingBuilt).AsInvalidProtocolBufferException();
} }
return BuildPartial();
IBuilder<TMessage> IBuilder<TMessage>.MergeFrom(byte[] data) {
throw new NotImplementedException();
} }
IBuilder<TMessage> IBuilder<TMessage>.MergeFrom(byte[] data, ExtensionRegistry extensionRegistry) { /// <summary>
throw new NotImplementedException(); /// Implementation of <see cref="IBuilder{T}.Build" />.
/// TODO(jonskeet): This used to be generated for each class. Find out why.
/// </summary>
public TMessage Build() {
if (!Initialized) {
throw new UninitializedMessageException(MessageBeingBuilt);
} }
return BuildPartial();
IBuilder<TMessage> IBuilder<TMessage>.MergeFrom(System.IO.Stream input) {
throw new NotImplementedException();
} }
IBuilder<TMessage> IBuilder<TMessage>.MergeFrom(System.IO.Stream input, ExtensionRegistry extensionRegistry) { public abstract TMessage BuildPartial();
throw new NotImplementedException(); public abstract IBuilder<TMessage> Clone();
} public abstract new IBuilder<TMessage> Clear();
public abstract TMessage DefaultInstanceForType { get; }
public abstract IBuilder<TMessage> MergeFrom(CodedInputStream input);
public abstract IBuilder<TMessage> MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry);
} }
} }
...@@ -16,7 +16,7 @@ namespace Google.ProtocolBuffers { ...@@ -16,7 +16,7 @@ namespace Google.ProtocolBuffers {
private readonly UnknownFieldSet unknownFields = UnknownFieldSet.DefaultInstance; private readonly UnknownFieldSet unknownFields = UnknownFieldSet.DefaultInstance;
protected internal abstract FieldAccessorTable<TMessage, TBuilder> InternalFieldAccessors { get; } protected internal abstract FieldAccessorTable InternalFieldAccessors { get; }
public override MessageDescriptor DescriptorForType { public override MessageDescriptor DescriptorForType {
get { return InternalFieldAccessors.Descriptor; } get { return InternalFieldAccessors.Descriptor; }
...@@ -30,13 +30,9 @@ namespace Google.ProtocolBuffers { ...@@ -30,13 +30,9 @@ namespace Google.ProtocolBuffers {
return CreateBuilderForType(); return CreateBuilderForType();
} }
public IMessage<TMessage> DefaultInstanceForType { public abstract TMessage DefaultInstanceForType { get; }
get { throw new NotImplementedException(); }
}
public IBuilder<TMessage> CreateBuilderForType() { public abstract IBuilder<TMessage> CreateBuilderForType();
throw new NotImplementedException();
}
private IDictionary<FieldDescriptor, Object> GetMutableFieldMap() { private IDictionary<FieldDescriptor, Object> GetMutableFieldMap() {
...@@ -44,7 +40,7 @@ namespace Google.ProtocolBuffers { ...@@ -44,7 +40,7 @@ namespace Google.ProtocolBuffers {
var ret = new SortedList<FieldDescriptor, object>(); var ret = new SortedList<FieldDescriptor, object>();
MessageDescriptor descriptor = DescriptorForType; MessageDescriptor descriptor = DescriptorForType;
foreach (FieldDescriptor field in descriptor.Fields) { foreach (FieldDescriptor field in descriptor.Fields) {
IFieldAccessor<TMessage, TBuilder> accessor = InternalFieldAccessors[field]; IFieldAccessor accessor = InternalFieldAccessors[field];
if ((field.IsRepeated && accessor.GetRepeatedCount(this) != 0) if ((field.IsRepeated && accessor.GetRepeatedCount(this) != 0)
|| accessor.Has(this)) { || accessor.Has(this)) {
ret[field] = accessor.GetValue(this); ret[field] = accessor.GetValue(this);
......
...@@ -125,7 +125,7 @@ namespace Google.ProtocolBuffers { ...@@ -125,7 +125,7 @@ namespace Google.ProtocolBuffers {
/// </summary> /// </summary>
/// <param name="other"></param> /// <param name="other"></param>
/// <returns></returns> /// <returns></returns>
IBuilder<T> MergeFrom(IMessage<T> other); IBuilder<T> MergeFrom(T other);
/// <summary> /// <summary>
/// Constructs the final message. Once this is called, this Builder instance /// Constructs the final message. Once this is called, this Builder instance
...@@ -142,7 +142,6 @@ namespace Google.ProtocolBuffers { ...@@ -142,7 +142,6 @@ namespace Google.ProtocolBuffers {
/// Like Build(), but does not throw an exception if the message is missing /// Like Build(), but does not throw an exception if the message is missing
/// required fields. Instead, a partial message is returned. /// required fields. Instead, a partial message is returned.
/// </summary> /// </summary>
/// <returns></returns>
new T BuildPartial(); new T BuildPartial();
/// <summary> /// <summary>
......
...@@ -179,8 +179,7 @@ namespace Google.ProtocolBuffers { ...@@ -179,8 +179,7 @@ namespace Google.ProtocolBuffers {
/// method is an abstract method of IMessage whereas DefaultInstance is /// method is an abstract method of IMessage whereas DefaultInstance is
/// a static property of a specific class. They return the same thing. /// a static property of a specific class. They return the same thing.
/// </summary> /// </summary>
new IMessage<T> DefaultInstanceForType { get; } new T DefaultInstanceForType { get; }
#region Builders #region Builders
/// <summary> /// <summary>
......
...@@ -24,7 +24,7 @@ namespace Google.ProtocolBuffers { ...@@ -24,7 +24,7 @@ namespace Google.ProtocolBuffers {
/// </summary> /// </summary>
public class InvalidProtocolBufferException : IOException { public class InvalidProtocolBufferException : IOException {
private InvalidProtocolBufferException(string message) internal InvalidProtocolBufferException(string message)
: base(message) { : base(message) {
} }
......
...@@ -13,7 +13,6 @@ using System.Runtime.InteropServices; ...@@ -13,7 +13,6 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCopyright("Copyright © 2008")] [assembly: AssemblyCopyright("Copyright © 2008")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
[assembly: AssemblyKeyFile ("Google.ProtocolBuffers.snk")]
// Setting ComVisible to false makes the types in this assembly not visible // Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from // to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type. // COM, set the ComVisible attribute to true on that type.
......
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
<AssemblyName>Google.ProtocolBuffers</AssemblyName> <AssemblyName>Google.ProtocolBuffers</AssemblyName>
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion> <TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>Properties\Google.ProtocolBuffers.snk</AssemblyOriginatorKeyFile>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
...@@ -45,10 +47,13 @@ ...@@ -45,10 +47,13 @@
<Compile Include="Collections\Lists.cs" /> <Compile Include="Collections\Lists.cs" />
<Compile Include="Collections\ReadOnlyDictionary.cs" /> <Compile Include="Collections\ReadOnlyDictionary.cs" />
<Compile Include="DescriptorProtos\Autogenerated.cs" /> <Compile Include="DescriptorProtos\Autogenerated.cs" />
<Compile Include="DescriptorProtos\DescriptorProtoFile.cs" />
<Compile Include="DescriptorProtos\IDescriptorProto.cs" /> <Compile Include="DescriptorProtos\IDescriptorProto.cs" />
<Compile Include="DescriptorProtos\PartialClasses.cs" /> <Compile Include="DescriptorProtos\PartialClasses.cs" />
<Compile Include="Descriptors\DescriptorBase.cs" /> <Compile Include="Descriptors\DescriptorBase.cs" />
<Compile Include="Descriptors\DescriptorPool.cs" />
<Compile Include="Descriptors\EnumDescriptor.cs" /> <Compile Include="Descriptors\EnumDescriptor.cs" />
<Compile Include="Descriptors\EnumDescriptorIndexAttribute.cs" />
<Compile Include="Descriptors\EnumValueDescriptor.cs" /> <Compile Include="Descriptors\EnumValueDescriptor.cs" />
<Compile Include="Descriptors\FieldDescriptor.cs" /> <Compile Include="Descriptors\FieldDescriptor.cs" />
<Compile Include="Descriptors\FieldMappingAttribute.cs" /> <Compile Include="Descriptors\FieldMappingAttribute.cs" />
...@@ -77,6 +82,9 @@ ...@@ -77,6 +82,9 @@
<Compile Include="UnknownFieldSet.cs" /> <Compile Include="UnknownFieldSet.cs" />
<Compile Include="WireFormat.cs" /> <Compile Include="WireFormat.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<None Include="Properties\Google.ProtocolBuffers.snk" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.
......
...@@ -17,5 +17,12 @@ using System; ...@@ -17,5 +17,12 @@ using System;
namespace Google.ProtocolBuffers { namespace Google.ProtocolBuffers {
public class UninitializedMessageException : Exception { public class UninitializedMessageException : Exception {
public UninitializedMessageException(IMessage message) {
}
public InvalidProtocolBufferException AsInvalidProtocolBufferException() {
return new InvalidProtocolBufferException(Message);
}
} }
} }
...@@ -70,7 +70,7 @@ void EnumGenerator::Generate(io::Printer* printer) { ...@@ -70,7 +70,7 @@ void EnumGenerator::Generate(io::Printer* printer) {
// TODO(jonskeet): Change CONSTANT_CASE into PascalCase // TODO(jonskeet): Change CONSTANT_CASE into PascalCase
printer->Print(vars, printer->Print(vars,
"[pb::DescriptorIndex($index$)]\r\n" "[pbd::EnumDescriptorIndex($index$)]\r\n"
"$name$ = $number$,\r\n"); "$name$ = $number$,\r\n");
} }
printer->Outdent(); printer->Outdent();
......
...@@ -68,20 +68,25 @@ EnumFieldGenerator::~EnumFieldGenerator() {} ...@@ -68,20 +68,25 @@ EnumFieldGenerator::~EnumFieldGenerator() {}
void EnumFieldGenerator:: void EnumFieldGenerator::
GenerateMembers(io::Printer* printer) const { GenerateMembers(io::Printer* printer) const {
printer->Print(variables_, printer->Print(variables_,
"private boolean has$capitalized_name$;\r\n" "private bool has$capitalized_name$;\r\n"
"private $type$ $name$_ = $default$;\r\n" "private $type$ $name$_ = $default$;\r\n"
"public boolean Has$capitalized_name$() { return has$capitalized_name$; }\r\n" "public bool Has$capitalized_name$ {\r\n"
"public $type$ Get$capitalized_name$() { return $name$_; }\r\n"); " get { return has$capitalized_name$; }\r\n"
"}\r\n"
"public $type$ $capitalized_name$ {"
" get { return $name$_; }"
"}\r\n");
} }
void EnumFieldGenerator:: void EnumFieldGenerator::
GenerateBuilderMembers(io::Printer* printer) const { GenerateBuilderMembers(io::Printer* printer) const {
printer->Print(variables_, printer->Print(variables_,
"public boolean Has$capitalized_name$() {\r\n" "public bool Has$capitalized_name$ {\r\n"
" return result.Has$capitalized_name$();\r\n" " get { return result.Has$capitalized_name$; }\r\n"
"}\r\n" "}\r\n"
"public $type$ Get$capitalized_name$() {\r\n" "public $type$ $capitalized_name$ {\r\n"
" return result.Get$capitalized_name$();\r\n" " get { return result.$capitalized_name$; }\r\n"
" set { Set$capitalized_name$(value); }\r\n"
"}\r\n" "}\r\n"
"public Builder Set$capitalized_name$($type$ value) {\r\n" "public Builder Set$capitalized_name$($type$ value) {\r\n"
" result.has$capitalized_name$ = true;\r\n" " result.has$capitalized_name$ = true;\r\n"
...@@ -98,8 +103,8 @@ GenerateBuilderMembers(io::Printer* printer) const { ...@@ -98,8 +103,8 @@ GenerateBuilderMembers(io::Printer* printer) const {
void EnumFieldGenerator:: void EnumFieldGenerator::
GenerateMergingCode(io::Printer* printer) const { GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_, printer->Print(variables_,
"if (other.has$capitalized_name$()) {\r\n" "if (other.Has$capitalized_name$) {\r\n"
" set$capitalized_name$(other.get$capitalized_name$());\r\n" " $capitalized_name$ = other.$capitalized_name$;\r\n"
"}\r\n"); "}\r\n");
} }
...@@ -111,36 +116,32 @@ GenerateBuildingCode(io::Printer* printer) const { ...@@ -111,36 +116,32 @@ GenerateBuildingCode(io::Printer* printer) const {
void EnumFieldGenerator:: void EnumFieldGenerator::
GenerateParsingCode(io::Printer* printer) const { GenerateParsingCode(io::Printer* printer) const {
printer->Print(variables_, printer->Print(variables_,
"int rawValue = input.readEnum();\r\n" // TODO(jonskeet): Make a more efficient way of doing this
"$type$ value = $type$.valueOf(rawValue);\r\n" "int rawValue = input.ReadEnum();\r\n"
"if (value == null) {\r\n" "if (!global::System.Enum.IsDefined(typeof($type$), rawValue)) {\r\n"
" unknownFields.mergeVarintField($number$, rawValue);\r\n" " unknownFields.MergeVarintField($number$, (ulong) rawValue);\r\n"
"} else {\r\n" "} else {\r\n"
" set$capitalized_name$(value);\r\n" " $capitalized_name$ = ($type$) rawValue;\r\n"
"}\r\n"); "}\r\n");
} }
void EnumFieldGenerator:: void EnumFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const { GenerateSerializationCode(io::Printer* printer) const {
printer->Print(variables_, printer->Print(variables_,
"if (has$capitalized_name$()) {\r\n" "if (Has$capitalized_name$) {\r\n"
" output.writeEnum($number$, get$capitalized_name$().getNumber());\r\n" " output.WriteEnum($number$, (int) $capitalized_name$);\r\n"
"}\r\n"); "}\r\n");
} }
void EnumFieldGenerator:: void EnumFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const { GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_, printer->Print(variables_,
"if (has$capitalized_name$()) {\r\n" "if (Has$capitalized_name$) {\r\n"
" size += pb::CodedOutputStream\r\n" " size += pb::CodedOutputStream\r\n"
" .computeEnumSize($number$, get$capitalized_name$().getNumber());\r\n" " .ComputeEnumSize($number$, (int) $capitalized_name$);\r\n"
"}\r\n"); "}\r\n");
} }
string EnumFieldGenerator::GetBoxedType() const {
return ClassName(descriptor_->enum_type());
}
// =================================================================== // ===================================================================
RepeatedEnumFieldGenerator:: RepeatedEnumFieldGenerator::
...@@ -154,17 +155,19 @@ RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {} ...@@ -154,17 +155,19 @@ RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
void RepeatedEnumFieldGenerator:: void RepeatedEnumFieldGenerator::
GenerateMembers(io::Printer* printer) const { GenerateMembers(io::Printer* printer) const {
printer->Print(variables_, printer->Print(variables_,
"private System.Collections.Generic.List<$type$> $name$_ =\r\n" "private scg::IList<$type$> $name$_ = new scg::List<$type$> ();\r\n"
" new System.Collections.Generic.List<$type$> ();\r\n" "public scg.IList<$type$> $capitalized_name$List {\r\n"
"public System.Collections.Generic.List<$type$> $capitalized_name$List() {\r\n" " get { return pbc::Lists.AsReadOnly($name$_); }\r\n" // note: unmodifiable list
" return $name$_.AsReadOnly ();\r\n" // note: unmodifiable list
"}\r\n" "}\r\n"
// Redundant API calls? // Redundant API calls?
//"public int $capitalized_name$Count() { get { return $name$_.Count; } }\r\n" // TODO(jonskeet): Possibly. Include for portability to start with though.
//"public $type$ get$capitalized_name$(int index) {\r\n" "public int $capitalized_name$Count {\r\n"
//" return $name$_.get(index);\r\n" " get { return $name$_.Count; }\r\n"
//"}\r\n" "}\r\n"
"public $type$ Get$capitalized_name$(int index) {\r\n"
" return $name$_[index];\r\n"
"}\r\n"
); );
} }
...@@ -175,36 +178,35 @@ GenerateBuilderMembers(io::Printer* printer) const { ...@@ -175,36 +178,35 @@ 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$> get$capitalized_name$List() {\r\n" "public global::System.Collections.Generic::IList<$type$> $capitalized_name$List {\r\n"
" return java.util.Collections.unmodifiableList(result.$name$_);\r\n" " get { return pbc::Lists.AsReadOnly(result.$name$_); }\r\n"
"}\r\n" "}\r\n"
"public int get$capitalized_name$Count() {\r\n" "public int $capitalized_name$Count {\r\n"
" return result.get$capitalized_name$Count();\r\n" " get { return result.get$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"
"}\r\n" "}\r\n"
"public Builder set$capitalized_name$(int index, $type$ value) {\r\n" "public Builder Set$capitalized_name$(int index, $type$ value) {\r\n"
" result.$name$_.set(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$_.isEmpty()) {\r\n" " if (result.$name$_.Count == 0) {\r\n"
" result.$name$_ = new java.util.ArrayList<$type$>();\r\n" " result.$name$_ = new scg::List<$type$>();\r\n"
" }\r\n" " }\r\n"
" result.$name$_.add(value);\r\n" " result.$name$_.Add(value);\r\n"
" return this;\r\n" " return this;\r\n"
"}\r\n" "}\r\n"
"public Builder addAll$capitalized_name$<T>(\r\n" "public Builder AddAll$capitalized_name$(scg::IEnumerable<$type$> values) {\r\n"
" global::System.Collections.Generic.IEnumerable<T> values) where T : $type$ {\r\n" " if (result.$name$_.Count == 0) {\r\n"
" if (result.$name$_.isEmpty()) {\r\n" " result.$name$_ = new scg::List<$type$>();\r\n"
" result.$name$_ = new java.util.ArrayList<$type$>();\r\n"
" }\r\n" " }\r\n"
" super.addAll(values, result.$name$_);\r\n" " base.AddRange(values, result.$name$_);\r\n"
" return this;\r\n" " return this;\r\n"
"}\r\n" "}\r\n"
"public Builder clear$capitalized_name$() {\r\n" "public Builder Clear$capitalized_name$() {\r\n"
" result.$name$_ = java.util.Collections.emptyList();\r\n" " result.$name$_ = pbc::Lists<$type$>.Empty;\r\n"
" return this;\r\n" " return this;\r\n"
"}\r\n"); "}\r\n");
} }
...@@ -212,56 +214,49 @@ GenerateBuilderMembers(io::Printer* printer) const { ...@@ -212,56 +214,49 @@ GenerateBuilderMembers(io::Printer* printer) const {
void RepeatedEnumFieldGenerator:: void RepeatedEnumFieldGenerator::
GenerateMergingCode(io::Printer* printer) const { GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_, printer->Print(variables_,
"if (!other.$name$_.isEmpty()) {\r\n" "if (other.$name$_.Count != 0) {\r\n"
" if (result.$name$_.isEmpty()) {\r\n" " if (result.$name$_.Count == 0) {\r\n"
" result.$name$_ = new java.util.ArrayList<$type$>();\r\n" " result.$name$_ = new scg::List<$type$>();\r\n"
" }\r\n" " }\r\n"
" result.$name$_.addAll(other.$name$_);\r\n" " base.AddRange(other.$name$_, result.$name$_);\r\n"
"}\r\n"); "}\r\n");
} }
void RepeatedEnumFieldGenerator:: void RepeatedEnumFieldGenerator::
GenerateBuildingCode(io::Printer* printer) const { GenerateBuildingCode(io::Printer* printer) const {
printer->Print(variables_, printer->Print(variables_,
"if (result.$name$_ != java.util.Collections.EMPTY_LIST) {\r\n" "result.$name$_ = pbc::Lists.AsReadOnly(result.$name$_);\r\n");
" result.$name$_ =\r\n"
" java.util.Collections.unmodifiableList(result.$name$_);\r\n"
"}\r\n");
} }
void RepeatedEnumFieldGenerator:: 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$.valueOf(rawValue);\r\n"
"if (value == null) {\r\n" "if (value == null) {\r\n"
" unknownFields.mergeVarintField($number$, rawValue);\r\n" " unknownFields.MergeVarintField($number$, 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");
} }
void RepeatedEnumFieldGenerator:: void RepeatedEnumFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const { GenerateSerializationCode(io::Printer* printer) const {
printer->Print(variables_, printer->Print(variables_,
"for ($type$ element : get$capitalized_name$List()) {\r\n" "foreach ($type$ element in $capitalized_name$List) {\r\n"
" output.writeEnum($number$, element.getNumber());\r\n" " output.WriteEnum($number$, element.Number);\r\n"
"}\r\n"); "}\r\n");
} }
void RepeatedEnumFieldGenerator:: void RepeatedEnumFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const { GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_, printer->Print(variables_,
"for ($type$ element : get$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.getNumber());\r\n" " .ComputeEnumSize($number$, element.Number);\r\n"
"}\r\n"); "}\r\n");
} }
string RepeatedEnumFieldGenerator::GetBoxedType() const {
return ClassName(descriptor_->enum_type());
}
} // namespace csharp } // namespace csharp
} // namespace compiler } // namespace compiler
} // namespace protobuf } // namespace protobuf
......
...@@ -45,8 +45,6 @@ class EnumFieldGenerator : public FieldGenerator { ...@@ -45,8 +45,6 @@ class EnumFieldGenerator : public FieldGenerator {
void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const; void GenerateSerializedSizeCode(io::Printer* printer) const;
string GetBoxedType() const;
private: private:
const FieldDescriptor* descriptor_; const FieldDescriptor* descriptor_;
map<string, string> variables_; map<string, string> variables_;
......
...@@ -40,17 +40,17 @@ void ExtensionGenerator::Generate(io::Printer* printer) { ...@@ -40,17 +40,17 @@ void ExtensionGenerator::Generate(io::Printer* printer) {
vars["containing_type"] = ClassName(descriptor_->containing_type()); vars["containing_type"] = ClassName(descriptor_->containing_type());
vars["index"] = SimpleItoa(descriptor_->index()); vars["index"] = SimpleItoa(descriptor_->index());
JavaType csharp_type = GetJavaType(descriptor_); MappedType mapped_type = GetMappedType(descriptor_);
string singular_type; string singular_type;
switch (csharp_type) { switch (mapped_type) {
case JAVATYPE_MESSAGE: case MAPPEDTYPE_MESSAGE:
vars["type"] = ClassName(descriptor_->message_type()); vars["type"] = ClassName(descriptor_->message_type());
break; break;
case JAVATYPE_ENUM: case MAPPEDTYPE_ENUM:
vars["type"] = ClassName(descriptor_->enum_type()); vars["type"] = ClassName(descriptor_->enum_type());
break; break;
default: default:
vars["type"] = BoxedPrimitiveTypeName(csharp_type); vars["type"] = MappedTypeName(mapped_type);
break; break;
} }
......
...@@ -51,19 +51,19 @@ FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor) ...@@ -51,19 +51,19 @@ FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor)
FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field) { FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field) {
if (field->is_repeated()) { if (field->is_repeated()) {
switch (GetJavaType(field)) { switch (GetMappedType(field)) {
case JAVATYPE_MESSAGE: case MAPPEDTYPE_MESSAGE:
return new RepeatedMessageFieldGenerator(field); return new RepeatedMessageFieldGenerator(field);
case JAVATYPE_ENUM: case MAPPEDTYPE_ENUM:
return new RepeatedEnumFieldGenerator(field); return new RepeatedEnumFieldGenerator(field);
default: default:
return new RepeatedPrimitiveFieldGenerator(field); return new RepeatedPrimitiveFieldGenerator(field);
} }
} else { } else {
switch (GetJavaType(field)) { switch (GetMappedType(field)) {
case JAVATYPE_MESSAGE: case MAPPEDTYPE_MESSAGE:
return new MessageFieldGenerator(field); return new MessageFieldGenerator(field);
case JAVATYPE_ENUM: case MAPPEDTYPE_ENUM:
return new EnumFieldGenerator(field); return new EnumFieldGenerator(field);
default: default:
return new PrimitiveFieldGenerator(field); return new PrimitiveFieldGenerator(field);
......
...@@ -50,8 +50,6 @@ class FieldGenerator { ...@@ -50,8 +50,6 @@ class FieldGenerator {
virtual void GenerateSerializationCode(io::Printer* printer) const = 0; virtual void GenerateSerializationCode(io::Printer* printer) const = 0;
virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0; virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0;
virtual string GetBoxedType() const = 0;
private: private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator); GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator);
}; };
......
...@@ -38,7 +38,7 @@ namespace csharp { ...@@ -38,7 +38,7 @@ namespace csharp {
FileGenerator::FileGenerator(const FileDescriptor* file) FileGenerator::FileGenerator(const FileDescriptor* file)
: file_(file), : file_(file),
csharp_namespace_(FileJavaPackage(file)), csharp_namespace_(FileCSharpNamespace(file)),
classname_(FileClassName(file)) {} classname_(FileClassName(file)) {}
FileGenerator::~FileGenerator() {} FileGenerator::~FileGenerator() {}
...@@ -72,9 +72,9 @@ bool FileGenerator::Validate(string* error) { ...@@ -72,9 +72,9 @@ bool FileGenerator::Validate(string* error) {
": Cannot generate C# output because the file's top-level class name, \""); ": Cannot generate C# output because the file's top-level class name, \"");
error->append(classname_); error->append(classname_);
error->append( error->append(
"\", matches the name of one of the types declared inside it. " "\", matches the name of one of the message, service or enum types. "
"Please either rename the type or use the csharp_outer_classname " "Please either rename the type or use the csharp_file_classname "
"option to specify a different outer class name for the .proto file."); "option to specify a different file-level class name for the .proto file.");
return false; return false;
} }
...@@ -88,24 +88,30 @@ void FileGenerator::Generate(io::Printer* printer) { ...@@ -88,24 +88,30 @@ void FileGenerator::Generate(io::Printer* printer) {
"// Generated by the protocol buffer compiler. DO NOT EDIT!\r\n" "// Generated by the protocol buffer compiler. DO NOT EDIT!\r\n"
"\r\n"); "\r\n");
// Namespace alias to avoid lines getting horribly long // Namespace aliases to avoid lines getting horribly long
printer->Print("using pb = global::Google.ProtocolBuffers;\r\n\r\n"); printer->Print("using pb = global::Google.ProtocolBuffers;\r\n");
printer->Print("using pbc = global::Google.ProtocolBuffers.Collections;\r\n");
printer->Print("using pbd = global::Google.ProtocolBuffers.Descriptors;\r\n");
printer->Print("using scg = global::System.Collections.Generic;\r\n");
if (!csharp_namespace_.empty()) { if (!csharp_namespace_.empty()) {
printer->Print("using self = global::$selfnamespace$;\r\n\r\n",
"selfnamespace", csharp_namespace_);
printer->Print( printer->Print(
"namespace $namespace$ {\r\n" "namespace $namespace$ {\r\n",
"\r\n",
"namespace", csharp_namespace_); "namespace", csharp_namespace_);
printer->Indent(); printer->Indent();
} }
printer->Print("\r\n");
printer->Print( printer->Print(
"public sealed class $classname$ {\r\n" "$access$ static partial class $classname$ {\r\n\r\n",
" private $classname$() {}\r\n", "classname", classname_,
"classname", classname_); "access", ClassAccessLevel(file_));
printer->Indent(); printer->Indent();
// ----------------------------------------------------------------- // -----------------------------------------------------------------
printer->Print("#region Descriptor\r\n");
// Embed the descriptor. We simply serialize the entire FileDescriptorProto // Embed the descriptor. We simply serialize the entire FileDescriptorProto
// and embed it as a byte array, which is parsed and built into real // and embed it as a byte array, which is parsed and built into real
// descriptors at initialization time. // descriptors at initialization time.
...@@ -115,10 +121,10 @@ void FileGenerator::Generate(io::Printer* printer) { ...@@ -115,10 +121,10 @@ void FileGenerator::Generate(io::Printer* printer) {
file_proto.SerializeToString(&file_data); file_proto.SerializeToString(&file_data);
printer->Print( printer->Print(
"public static pb::Descriptors.FileDescriptor Descriptor {\r\n" "public static pbd::FileDescriptor Descriptor {\r\n"
" get { return descriptor; }\r\n" " get { return descriptor; }\r\n"
"}\r\n" "}\r\n"
"private static readonly pb::Descriptors.FileDescriptor descriptor = pb::Descriptors.FileDescriptor.InternalBuildGeneratedFileFrom (\r\n" "private static readonly pbd::FileDescriptor descriptor = pbd::FileDescriptor.InternalBuildGeneratedFileFrom (\r\n"
" new byte[] {"); " new byte[] {");
printer->Indent(); printer->Indent();
printer->Indent(); printer->Indent();
...@@ -139,7 +145,7 @@ void FileGenerator::Generate(io::Printer* printer) { ...@@ -139,7 +145,7 @@ void FileGenerator::Generate(io::Printer* printer) {
} }
printer->Outdent(); printer->Outdent();
printer->Outdent(); printer->Outdent();
printer->Print("\r\n}, new pb::Descriptors.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$.getDescriptor(),\r\n",
...@@ -150,36 +156,58 @@ void FileGenerator::Generate(io::Printer* printer) { ...@@ -150,36 +156,58 @@ void FileGenerator::Generate(io::Printer* printer) {
printer->Outdent(); printer->Outdent();
printer->Outdent(); printer->Outdent();
printer->Print("\r\n"); printer->Print("#endregion\r\n\r\n");
// ----------------------------------------------------------------- // -----------------------------------------------------------------
if (!file_->options().csharp_multiple_files()) {
for (int i = 0; i < file_->enum_type_count(); i++) {
EnumGenerator(file_->enum_type(i)).Generate(printer);
}
for (int i = 0; i < file_->message_type_count(); i++) {
MessageGenerator(file_->message_type(i)).Generate(printer);
}
for (int i = 0; i < file_->service_count(); i++) {
ServiceGenerator(file_->service(i)).Generate(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");
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("#endregion\r\n\r\n");
printer->Print("#region Static variables\r\n");
// Static variables. // Static variables.
for (int i = 0; i < file_->message_type_count(); i++) { for (int i = 0; i < file_->message_type_count(); i++) {
// TODO(kenton): Reuse MessageGenerator objects? // TODO(kenton): Reuse MessageGenerator objects?
MessageGenerator(file_->message_type(i)).GenerateStaticVariables(printer); MessageGenerator(file_->message_type(i)).GenerateStaticVariables(printer);
} }
printer->Print("#endregion\r\n\r\n");
// If we're not nesting classes, the class for the .proto file is done now
if (!file_->options().csharp_nest_classes()) {
printer->Outdent(); printer->Outdent();
printer->Print("}\r\n"); printer->Print("}\r\n\r\n");
}
if (!file_->options().csharp_multiple_files()) {
printer->Print("#region Enums\r\n");
for (int i = 0; i < file_->enum_type_count(); i++) {
EnumGenerator(file_->enum_type(i)).Generate(printer);
}
printer->Print("#endregion\r\n\r\n");
printer->Print("#region Messages\r\n");
for (int i = 0; i < file_->message_type_count(); i++) {
MessageGenerator(file_->message_type(i)).Generate(printer);
}
printer->Print("#endregion\r\n\r\n");
printer->Print("#region Services\r\n");
for (int i = 0; i < file_->service_count(); i++) {
ServiceGenerator(file_->service(i)).Generate(printer);
}
printer->Print("#endregion\r\n");
}
// If we were nesting classes, we still need to finish the outer one at some point!
if (file_->options().csharp_nest_classes()) {
printer->Outdent();
printer->Print("}\r\n\r\n");
}
if (!csharp_namespace_.empty()) { if (!csharp_namespace_.empty()) {
printer->Outdent(); printer->Outdent();
printer->Print("}\r\n"); printer->Print("}\r\n");
...@@ -187,12 +215,12 @@ void FileGenerator::Generate(io::Printer* printer) { ...@@ -187,12 +215,12 @@ void FileGenerator::Generate(io::Printer* printer) {
} }
template<typename GeneratorClass, typename DescriptorClass> template<typename GeneratorClass, typename DescriptorClass>
static void GenerateSibling(const string& package_dir, static void GenerateSibling(const string& csharp_namespace,
const string& csharp_namespace, const FileDescriptor* file,
const DescriptorClass* descriptor, const DescriptorClass* descriptor,
OutputDirectory* output_directory, OutputDirectory* output_directory,
vector<string>* file_list) { vector<string>* file_list) {
string filename = package_dir + descriptor->name() + ".cs"; string filename = descriptor->name() + ".cs";
file_list->push_back(filename); file_list->push_back(filename);
scoped_ptr<io::ZeroCopyOutputStream> output( scoped_ptr<io::ZeroCopyOutputStream> output(
...@@ -203,40 +231,62 @@ static void GenerateSibling(const string& package_dir, ...@@ -203,40 +231,62 @@ static void GenerateSibling(const string& package_dir,
"// Generated by the protocol buffer compiler. DO NOT EDIT!\r\n" "// Generated by the protocol buffer compiler. DO NOT EDIT!\r\n"
"\r\n"); "\r\n");
// Namespace alias to avoid lines getting horribly long // Namespace aliases to avoid lines getting horribly long
printer.Print("using pb = global::Google.ProtocolBuffers;\r\n\r\n"); printer.Print("using pb = global::Google.ProtocolBuffers;\r\n");
printer.Print("using pbc = global::Google.ProtocolBuffers.Collections;\r\n");
printer.Print("using pbd = global::Google.ProtocolBuffers.Descriptors;\r\n");
printer.Print("using scg = global::System.Collections.Generic;\r\n");
if (!csharp_namespace.empty()) { if (!csharp_namespace.empty()) {
printer.Print("using self = global::$selfnamespace$;\r\n\r\n",
"selfnamespace", csharp_namespace);
printer.Print( printer.Print(
"namespace $namespace$ {\r\n" "namespace $namespace$ {\r\n",
"\r\n",
"namespace", csharp_namespace); "namespace", csharp_namespace);
printer.Indent(); printer.Indent();
} }
printer.Print("\r\n");
if (file->options().csharp_nest_classes()) {
printer.Print(
"$access$ static partial class $classname$ {\r\n\r\n",
"classname", FileClassName(file),
"access", ClassAccessLevel(file));
printer.Indent();
}
GeneratorClass(descriptor).Generate(&printer); GeneratorClass(descriptor).Generate(&printer);
if (file->options().csharp_nest_classes()) {
printer.Outdent();
printer.Print("}\r\n");
}
if (!csharp_namespace.empty()) { if (!csharp_namespace.empty()) {
printer.Outdent(); printer.Outdent();
printer.Print("}\r\n"); printer.Print("}\r\n");
} }
} }
void FileGenerator::GenerateSiblings(const string& package_dir, void FileGenerator::GenerateSiblings(OutputDirectory* output_directory,
OutputDirectory* output_directory,
vector<string>* file_list) { vector<string>* file_list) {
if (file_->options().csharp_multiple_files()) { if (file_->options().csharp_multiple_files()) {
for (int i = 0; i < file_->enum_type_count(); i++) { for (int i = 0; i < file_->enum_type_count(); i++) {
GenerateSibling<EnumGenerator>(package_dir, csharp_namespace_, GenerateSibling<EnumGenerator>(csharp_namespace_,
file_,
file_->enum_type(i), file_->enum_type(i),
output_directory, file_list); output_directory, file_list);
} }
for (int i = 0; i < file_->message_type_count(); i++) { for (int i = 0; i < file_->message_type_count(); i++) {
GenerateSibling<MessageGenerator>(package_dir, csharp_namespace_, GenerateSibling<MessageGenerator>(csharp_namespace_,
file_,
file_->message_type(i), file_->message_type(i),
output_directory, file_list); output_directory, file_list);
} }
for (int i = 0; i < file_->service_count(); i++) { for (int i = 0; i < file_->service_count(); i++) {
GenerateSibling<ServiceGenerator>(package_dir, csharp_namespace_, GenerateSibling<ServiceGenerator>(csharp_namespace_,
file_,
file_->service(i), file_->service(i),
output_directory, file_list); output_directory, file_list);
} }
......
...@@ -56,8 +56,7 @@ class FileGenerator { ...@@ -56,8 +56,7 @@ class FileGenerator {
// If we aren't putting everything into one file, this will write all the // If we aren't putting everything into one file, this will write all the
// files other than the outer file (i.e. one for each message, enum, and // files other than the outer file (i.e. one for each message, enum, and
// service type). // service type).
void GenerateSiblings(const string& package_dir, void GenerateSiblings(OutputDirectory* output_directory,
OutputDirectory* output_directory,
vector<string>* file_list); vector<string>* file_list);
const string& csharp_namespace() { return csharp_namespace_; } const string& csharp_namespace() { return csharp_namespace_; }
......
...@@ -93,25 +93,20 @@ bool CSharpGenerator::Generate(const FileDescriptor* file, ...@@ -93,25 +93,20 @@ bool CSharpGenerator::Generate(const FileDescriptor* file,
return false; return false;
} }
string package_dir =
StringReplace(file_generator.csharp_namespace(), ".", "/", true);
if (!package_dir.empty()) package_dir += "/";
vector<string> all_files; vector<string> all_files;
string csharp_filename = package_dir; string csharp_filename = file_generator.classname();
csharp_filename += file_generator.classname();
csharp_filename += ".cs"; csharp_filename += ".cs";
all_files.push_back(csharp_filename); all_files.push_back(csharp_filename);
// Generate main csharp file. // Generate main C# file.
scoped_ptr<io::ZeroCopyOutputStream> output( scoped_ptr<io::ZeroCopyOutputStream> output(
output_directory->Open(csharp_filename)); output_directory->Open(csharp_filename));
io::Printer printer(output.get(), '$'); io::Printer printer(output.get(), '$');
file_generator.Generate(&printer); file_generator.Generate(&printer);
// Generate sibling files. // Generate sibling files.
file_generator.GenerateSiblings(package_dir, output_directory, &all_files); file_generator.GenerateSiblings(output_directory, &all_files);
// Generate output list if requested. // Generate output list if requested.
if (!output_list_file.empty()) { if (!output_list_file.empty()) {
......
...@@ -104,8 +104,8 @@ string StripProto(const string& filename) { ...@@ -104,8 +104,8 @@ string StripProto(const string& filename) {
} }
string FileClassName(const FileDescriptor* file) { string FileClassName(const FileDescriptor* file) {
if (file->options().has_csharp_outer_classname()) { if (file->options().has_csharp_file_classname()) {
return file->options().csharp_outer_classname(); return file->options().csharp_file_classname();
} else { } else {
string basename; string basename;
string::size_type last_slash = file->name().find_last_of('/'); string::size_type last_slash = file->name().find_last_of('/');
...@@ -118,7 +118,7 @@ string FileClassName(const FileDescriptor* file) { ...@@ -118,7 +118,7 @@ string FileClassName(const FileDescriptor* file) {
} }
} }
string FileJavaPackage(const FileDescriptor* file) { string FileCSharpNamespace(const FileDescriptor* file) {
if (file->options().has_csharp_namespace()) { if (file->options().has_csharp_namespace()) {
return file->options().csharp_namespace(); return file->options().csharp_namespace();
} else { } else {
...@@ -131,99 +131,106 @@ string FileJavaPackage(const FileDescriptor* file) { ...@@ -131,99 +131,106 @@ string FileJavaPackage(const FileDescriptor* file) {
} }
} }
string ToJavaName(const string& full_name, const FileDescriptor* file) { string ToCSharpName(const string& full_name, const FileDescriptor* file) {
string result; string result;
if (file->options().csharp_multiple_files()) { if (!file->options().csharp_nest_classes()) {
result = FileJavaPackage(file); result = "";
} else { } else {
result = ClassName(file); result = ClassName(file);
} }
if (!result.empty()) { if (!result.empty()) {
result += '.'; result += '.';
} }
string classname;
if (file->package().empty()) { if (file->package().empty()) {
result += full_name; classname = full_name;
} else { } else {
// Strip the proto package from full_name since we've replaced it with // Strip the proto package from full_name since we've replaced it with
// the Java package. // the C# package.
result += full_name.substr(file->package().size() + 1); classname = full_name.substr(file->package().size() + 1);
} }
return result; result += StringReplace(classname, ".", ".Types.", true);
const char *prefix = FileCSharpNamespace(file).empty() ? "global::" : "self::";
return prefix + result;
} }
string ClassName(const FileDescriptor* descriptor) { string ClassName(const FileDescriptor* descriptor) {
string result = FileJavaPackage(descriptor); string alias = FileCSharpNamespace(descriptor).empty() ? "global::" : "self::";
if (!result.empty()) result += '.'; return alias + FileClassName(descriptor);
result += FileClassName(descriptor);
return result;
} }
JavaType GetJavaType(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_UINT32:
case FieldDescriptor::TYPE_SINT32: case FieldDescriptor::TYPE_SINT32:
case FieldDescriptor::TYPE_FIXED32: case FieldDescriptor::TYPE_FIXED32:
case FieldDescriptor::TYPE_SFIXED32: case FieldDescriptor::TYPE_SFIXED32:
return JAVATYPE_INT; return MAPPEDTYPE_INT;
case FieldDescriptor::TYPE_INT64: case FieldDescriptor::TYPE_INT64:
case FieldDescriptor::TYPE_UINT64: case FieldDescriptor::TYPE_UINT64:
case FieldDescriptor::TYPE_SINT64: case FieldDescriptor::TYPE_SINT64:
case FieldDescriptor::TYPE_FIXED64: case FieldDescriptor::TYPE_FIXED64:
case FieldDescriptor::TYPE_SFIXED64: case FieldDescriptor::TYPE_SFIXED64:
return JAVATYPE_LONG; return MAPPEDTYPE_LONG;
case FieldDescriptor::TYPE_FLOAT: case FieldDescriptor::TYPE_FLOAT:
return JAVATYPE_FLOAT; return MAPPEDTYPE_FLOAT;
case FieldDescriptor::TYPE_DOUBLE: case FieldDescriptor::TYPE_DOUBLE:
return JAVATYPE_DOUBLE; return MAPPEDTYPE_DOUBLE;
case FieldDescriptor::TYPE_BOOL: case FieldDescriptor::TYPE_BOOL:
return JAVATYPE_BOOLEAN; return MAPPEDTYPE_BOOLEAN;
case FieldDescriptor::TYPE_STRING: case FieldDescriptor::TYPE_STRING:
return JAVATYPE_STRING; return MAPPEDTYPE_STRING;
case FieldDescriptor::TYPE_BYTES: case FieldDescriptor::TYPE_BYTES:
return JAVATYPE_BYTES; return MAPPEDTYPE_BYTES;
case FieldDescriptor::TYPE_ENUM: case FieldDescriptor::TYPE_ENUM:
return JAVATYPE_ENUM; return MAPPEDTYPE_ENUM;
case FieldDescriptor::TYPE_GROUP: case FieldDescriptor::TYPE_GROUP:
case FieldDescriptor::TYPE_MESSAGE: case FieldDescriptor::TYPE_MESSAGE:
return JAVATYPE_MESSAGE; return MAPPEDTYPE_MESSAGE;
// No default because we want the compiler to complain if any new // No default because we want the compiler to complain if any new
// types are added. // types are added.
} }
GOOGLE_LOG(FATAL) << "Can't get here."; GOOGLE_LOG(FATAL) << "Can't get here.";
return JAVATYPE_INT; return MAPPEDTYPE_INT;
} }
const char* BoxedPrimitiveTypeName(JavaType type) { const char* MappedTypeName(MappedType type) {
switch (type) { switch (type) {
case JAVATYPE_INT : return "int"; case MAPPEDTYPE_INT : return "int";
case JAVATYPE_LONG : return "long"; case MAPPEDTYPE_LONG : return "long";
case JAVATYPE_FLOAT : return "float"; case MAPPEDTYPE_UINT : return "uint";
case JAVATYPE_DOUBLE : return "double"; case MAPPEDTYPE_ULONG : return "ulong";
case JAVATYPE_BOOLEAN: return "bool"; case MAPPEDTYPE_FLOAT : return "float";
case JAVATYPE_STRING : return "string"; case MAPPEDTYPE_DOUBLE : return "double";
case JAVATYPE_BYTES : return "pb::ByteString"; case MAPPEDTYPE_BOOLEAN: return "bool";
case JAVATYPE_ENUM : return NULL; case MAPPEDTYPE_STRING : return "string";
case JAVATYPE_MESSAGE: return NULL; case MAPPEDTYPE_BYTES : return "pb::ByteString";
case MAPPEDTYPE_ENUM : return NULL;
case MAPPEDTYPE_MESSAGE: return NULL;
// No default because we want the compiler to complain if any new // No default because we want the compiler to complain if any new
// JavaTypes are added. // MappedTypes are added.
} }
GOOGLE_LOG(FATAL) << "Can't get here."; GOOGLE_LOG(FATAL) << "Can't get here.";
return NULL; return NULL;
} }
const char* ClassAccessLevel(const FileDescriptor* file) {
return file->options().csharp_public_classes() ? "public" : "internal";
}
} // namespace csharp } // namespace csharp
} // namespace compiler } // namespace compiler
} // namespace protobuf } // namespace protobuf
......
...@@ -48,52 +48,56 @@ string UnderscoresToCamelCase(const MethodDescriptor* method); ...@@ -48,52 +48,56 @@ string UnderscoresToCamelCase(const MethodDescriptor* method);
string StripProto(const string& filename); string StripProto(const string& filename);
// Gets the unqualified class name for the file. Each .proto file becomes a // Gets the unqualified class name for the file. Each .proto file becomes a
// single Java class, with all its contents nested in that class. // single C# class, with extra (possibly nested) classes for messages, enums and services.
string FileClassName(const FileDescriptor* file); string FileClassName(const FileDescriptor* file);
// Returns the file's Java package name. // Returns the file's C# namespace.
string FileJavaPackage(const FileDescriptor* file); string FileCSharpNamespace(const FileDescriptor* file);
// Converts the given fully-qualified name in the proto namespace to its // Converts the given fully-qualified name in the proto namespace to its
// fully-qualified name in the Java namespace, given that it is in the given // fully-qualified name in the C# namespace, given that it is in the given
// file. // file.
string ToJavaName(const string& full_name, const FileDescriptor* file); string ToCSharpName(const string& full_name, const FileDescriptor* file);
// These return the fully-qualified class name corresponding to the given // These return the fully-qualified class name corresponding to the given
// descriptor. // descriptor.
inline string ClassName(const Descriptor* descriptor) { inline string ClassName(const Descriptor* descriptor) {
return ToJavaName(descriptor->full_name(), descriptor->file()); return ToCSharpName(descriptor->full_name(), descriptor->file());
} }
inline string ClassName(const EnumDescriptor* descriptor) { inline string ClassName(const EnumDescriptor* descriptor) {
return ToJavaName(descriptor->full_name(), descriptor->file()); return ToCSharpName(descriptor->full_name(), descriptor->file());
} }
inline string ClassName(const ServiceDescriptor* descriptor) { inline string ClassName(const ServiceDescriptor* descriptor) {
return ToJavaName(descriptor->full_name(), descriptor->file()); return ToCSharpName(descriptor->full_name(), descriptor->file());
} }
string ClassName(const FileDescriptor* descriptor); string ClassName(const FileDescriptor* descriptor);
enum JavaType { enum MappedType {
JAVATYPE_INT, MAPPEDTYPE_INT,
JAVATYPE_LONG, MAPPEDTYPE_LONG,
JAVATYPE_FLOAT, MAPPEDTYPE_UINT,
JAVATYPE_DOUBLE, MAPPEDTYPE_ULONG,
JAVATYPE_BOOLEAN, MAPPEDTYPE_FLOAT,
JAVATYPE_STRING, MAPPEDTYPE_DOUBLE,
JAVATYPE_BYTES, MAPPEDTYPE_BOOLEAN,
JAVATYPE_ENUM, MAPPEDTYPE_STRING,
JAVATYPE_MESSAGE MAPPEDTYPE_BYTES,
MAPPEDTYPE_ENUM,
MAPPEDTYPE_MESSAGE
}; };
JavaType GetJavaType(FieldDescriptor::Type field_type); MappedType GetMappedType(FieldDescriptor::Type field_type);
inline JavaType GetJavaType(const FieldDescriptor* field) { inline MappedType GetMappedType(const FieldDescriptor* field) {
return GetJavaType(field->type()); return GetMappedType(field->type());
} }
// Get the fully-qualified class name for a boxed primitive type, e.g. // Get the access level for generated classes: public or internal
// "java.lang.Integer" for JAVATYPE_INT. Returns NULL for enum and message const char* ClassAccessLevel(const FileDescriptor* file);
// types.
const char* BoxedPrimitiveTypeName(JavaType type); // Get the class name for a built-in type (including ByteString).
// Returns NULL for enum and message types.
const char* MappedTypeName(MappedType type);
} // namespace csharp } // namespace csharp
} // namespace compiler } // namespace compiler
......
...@@ -45,8 +45,6 @@ class MessageFieldGenerator : public FieldGenerator { ...@@ -45,8 +45,6 @@ class MessageFieldGenerator : public FieldGenerator {
void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const; void GenerateSerializedSizeCode(io::Printer* printer) const;
string GetBoxedType() const;
private: private:
const FieldDescriptor* descriptor_; const FieldDescriptor* descriptor_;
map<string, string> variables_; map<string, string> variables_;
......
...@@ -45,8 +45,6 @@ class PrimitiveFieldGenerator : public FieldGenerator { ...@@ -45,8 +45,6 @@ class PrimitiveFieldGenerator : public FieldGenerator {
void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const; void GenerateSerializedSizeCode(io::Printer* printer) const;
string GetBoxedType() const;
private: private:
const FieldDescriptor* descriptor_; const FieldDescriptor* descriptor_;
map<string, string> variables_; map<string, string> variables_;
...@@ -68,8 +66,6 @@ class RepeatedPrimitiveFieldGenerator : public FieldGenerator { ...@@ -68,8 +66,6 @@ class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const; void GenerateSerializedSizeCode(io::Printer* printer) const;
string GetBoxedType() const;
private: private:
const FieldDescriptor* descriptor_; const FieldDescriptor* descriptor_;
map<string, string> variables_; map<string, string> variables_;
......
...@@ -62,12 +62,12 @@ void ServiceGenerator::Generate(io::Printer* printer) { ...@@ -62,12 +62,12 @@ void ServiceGenerator::Generate(io::Printer* printer) {
printer->Print( printer->Print(
"\r\n" "\r\n"
"public static final\r\n" "public static final\r\n"
" pb::Descriptors.ServiceDescriptor\r\n" " pbd::ServiceDescriptor\r\n"
" getDescriptor() {\r\n" " getDescriptor() {\r\n"
" return $file$.getDescriptor().getServices().get($index$);\r\n" " return $file$.getDescriptor().getServices().get($index$);\r\n"
"}\r\n" "}\r\n"
"public final pb::Descriptors.ServiceDescriptor\r\n" "public final pbd::ServiceDescriptor\r\n"
" getDescriptorForType() {\r\n" " DescriptorForType {\r\n"
" return getDescriptor();\r\n" " return getDescriptor();\r\n"
"}\r\n", "}\r\n",
"file", ClassName(descriptor_->file()), "file", ClassName(descriptor_->file()),
...@@ -87,14 +87,14 @@ void ServiceGenerator::GenerateCallMethod(io::Printer* printer) { ...@@ -87,14 +87,14 @@ void ServiceGenerator::GenerateCallMethod(io::Printer* printer) {
printer->Print( printer->Print(
"\r\n" "\r\n"
"public final void callMethod(\r\n" "public final void callMethod(\r\n"
" pb::Descriptors.MethodDescriptor method,\r\n" " pbd::MethodDescriptor method,\r\n"
" pb::RpcController controller,\r\n" " pb::RpcController controller,\r\n"
" pb::Message request,\r\n" " pb::IMessage request,\r\n"
" pb::RpcCallback<\r\n" " pb::RpcCallback<\r\n"
" pb::Message> done) {\r\n" " pb::Message> done) {\r\n"
" if (method.getService() != getDescriptor()) {\r\n" " if (method.getService() != getDescriptor()) {\r\n"
" throw new java.lang.IllegalArgumentException(\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.getIndex()) {\r\n");
...@@ -118,7 +118,7 @@ void ServiceGenerator::GenerateCallMethod(io::Printer* printer) { ...@@ -118,7 +118,7 @@ void ServiceGenerator::GenerateCallMethod(io::Printer* printer) {
printer->Print( printer->Print(
"default:\r\n" "default:\r\n"
" throw new java.lang.RuntimeException(\"Can't get here.\");\r\n"); " throw new global::System.InvalidOperationException(\"Can't get here.\");\r\n");
printer->Outdent(); printer->Outdent();
printer->Outdent(); printer->Outdent();
...@@ -133,14 +133,14 @@ void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which, ...@@ -133,14 +133,14 @@ void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which,
io::Printer* printer) { io::Printer* printer) {
printer->Print( printer->Print(
"public final pb::Message\r\n" "public final pb::Message\r\n"
" get$request_or_response$Prototype(\r\n" " Get$request_or_response$Prototype(\r\n"
" pb::Descriptors.MethodDescriptor method) {\r\n" " pbd::MethodDescriptor method) {\r\n"
" if (method.getService() != getDescriptor()) {\r\n" " if (method.getService() != getDescriptor()) {\r\n"
" throw new java.lang.IllegalArgumentException(\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"
" }\r\n" " }\r\n"
" switch(method.getIndex()) {\r\n", " switch(method.Index) {\r\n",
"request_or_response", (which == REQUEST) ? "Request" : "Response"); "request_or_response", (which == REQUEST) ? "Request" : "Response");
printer->Indent(); printer->Indent();
printer->Indent(); printer->Indent();
...@@ -153,12 +153,12 @@ void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which, ...@@ -153,12 +153,12 @@ void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which,
(which == REQUEST) ? method->input_type() : method->output_type()); (which == REQUEST) ? method->input_type() : method->output_type());
printer->Print(vars, printer->Print(vars,
"case $index$:\r\n" "case $index$:\r\n"
" return $type$.getDefaultInstance();\r\n"); " return $type$.DefaultInstance;\r\n");
} }
printer->Print( printer->Print(
"default:\r\n" "default:\r\n"
" throw new java.lang.RuntimeException(\"Can't get here.\");\r\n"); " throw new global::System.ArgumentException(\"Can't get here.\");\r\n");
printer->Outdent(); printer->Outdent();
printer->Outdent(); printer->Outdent();
...@@ -205,14 +205,14 @@ void ServiceGenerator::GenerateStub(io::Printer* printer) { ...@@ -205,14 +205,14 @@ void ServiceGenerator::GenerateStub(io::Printer* printer) {
" $input$ request,\r\n" " $input$ request,\r\n"
" pb::RpcCallback<$output$> done) {\r\n" " pb::RpcCallback<$output$> done) {\r\n"
" channel.callMethod(\r\n" " channel.callMethod(\r\n"
" getDescriptor().getMethods().get($index$),\r\n" " Descriptor.Methods[$index$],\r\n"
" controller,\r\n" " controller,\r\n"
" request,\r\n" " request,\r\n"
" $output$.getDefaultInstance(),\r\n" " $output$.DefaultInstance,\r\n"
" pb::RpcUtil.generalizeCallback(\r\n" " pb::RpcUtil.generalizeCallback(\r\n"
" done,\r\n" " done,\r\n"
" typeof ($output$),\r\n" " typeof ($output$),\r\n"
" $output$.getDefaultInstance()));\r\n" " $output$.DefaultInstance));\r\n"
"}\r\n"); "}\r\n");
} }
......
...@@ -28,8 +28,11 @@ package google.protobuf; ...@@ -28,8 +28,11 @@ package google.protobuf;
option java_package = "com.google.protobuf"; option java_package = "com.google.protobuf";
option java_outer_classname = "DescriptorProtos"; option java_outer_classname = "DescriptorProtos";
option csharp_namespace = "Google.ProtocolBuffers"; option csharp_namespace = "Google.ProtocolBuffers.DescriptorProtos";
option csharp_outer_classname = "DescriptorProtos"; option csharp_file_classname = "DescriptorProtoFile";
option csharp_multiple_files = false;
option csharp_nest_classes = false;
option csharp_public_classes = true;
// descriptor.proto must be optimized for speed because reflection-based // descriptor.proto must be optimized for speed because reflection-based
// algorithms don't work during bootstrapping. // algorithms don't work during bootstrapping.
...@@ -223,10 +226,35 @@ message FileOptions { ...@@ -223,10 +226,35 @@ message FileOptions {
optional OptimizeMode optimize_for = 9 [default=CODE_SIZE]; optional OptimizeMode optimize_for = 9 [default=CODE_SIZE];
// C# stuff... remove eventually? // C# stuff... generalise to .NET?
// Sets the namespace where classes generated from this .proto will be
// placed. By default, the proto package is used. Unlike the Java
// generator, the C# generator does *not* create a directory structure
// based on the namespace.
optional string csharp_namespace = 1000; optional string csharp_namespace = 1000;
optional string csharp_outer_classname = 1001;
optional bool csharp_multiple_files = 1002; // One class is generated to represent the .proto file as a whole.
// It contains the file's descriptor as well as any top-level
// extensions.
optional string csharp_file_classname = 1001;
// If set true, the C# generator will generate a separate .cs file
// for each top-level message, enum and service defined in the .proto
// file. Otherwise, a single .cs file will be generated.
optional bool csharp_multiple_files = 1002 [default=false];
// If set true, the C# generator will use the "whole .proto file" class
// as a container for all the other classes. This value is independent
// of csharp_multiple_files - using partial types, the C# generator
// can still nest classes even when generating multiple files,
// and C# allows multiple public top-level classes in the same
// file.
optional bool csharp_nest_classes = 1003 [default=false];
// If set true, the C# generator will make all its generated classes
// public. If set false, classes will be internal (i.e. only
// visible within the same assembly).
optional bool csharp_public_classes = 1004 [default=true];
} }
message MessageOptions { message MessageOptions {
......
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