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 = \
Google.ProtocolBuffers.dll: $(Google.ProtocolBuffers.dll_sources)
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
gacutil -i Google.ProtocolBuffers.dll -package google
......
......@@ -25,7 +25,6 @@ namespace Google.ProtocolBuffers {
protected abstract IMessage BuildPartialImpl();
protected abstract IBuilder CloneImpl();
protected abstract IMessage DefaultInstanceForTypeImpl { get; }
protected abstract IBuilder CreateBuilderForFieldImpl(FieldDescriptor field);
protected abstract IBuilder ClearFieldImpl(FieldDescriptor field);
protected abstract IBuilder AddRepeatedFieldImpl(FieldDescriptor field, object value);
#endregion
......@@ -47,9 +46,7 @@ namespace Google.ProtocolBuffers {
get { return DefaultInstanceForTypeImpl; }
}
IBuilder IBuilder.CreateBuilderForField(FieldDescriptor field) {
return CreateBuilderForFieldImpl(field);
}
public abstract IBuilder CreateBuilderForField(FieldDescriptor field);
IBuilder IBuilder.ClearField(FieldDescriptor field) {
return ClearFieldImpl(field);
......@@ -67,7 +64,7 @@ namespace Google.ProtocolBuffers {
return this;
}
public IBuilder MergeFrom(IMessage other) {
public virtual IBuilder MergeFrom(IMessage other) {
if (other.DescriptorForType != DescriptorForType) {
throw new ArgumentException("MergeFrom(Message) can only merge messages of the same type.");
}
......@@ -106,18 +103,18 @@ namespace Google.ProtocolBuffers {
return this;
}
public IBuilder MergeFrom(CodedInputStream input) {
return MergeFrom(input, ExtensionRegistry.Empty);
IBuilder IBuilder.MergeFrom(CodedInputStream input) {
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);
FieldSet.MergeFrom(input, unknownFields, extensionRegistry, this);
UnknownFields = unknownFields.Build();
return this;
}
public IBuilder MergeUnknownFields(UnknownFieldSet unknownFields) {
IBuilder IBuilder.MergeUnknownFields(UnknownFieldSet unknownFields) {
UnknownFields = UnknownFieldSet.CreateBuilder(UnknownFields)
.MergeFrom(unknownFields)
.Build();
......@@ -126,44 +123,44 @@ namespace Google.ProtocolBuffers {
public UnknownFieldSet UnknownFields { get; set; }
public IBuilder MergeFrom(ByteString data) {
IBuilder IBuilder.MergeFrom(ByteString data) {
CodedInputStream input = data.CreateCodedInput();
MergeFrom(input);
((IBuilder)this).MergeFrom(input);
input.CheckLastTagWas(0);
return this;
}
public IBuilder MergeFrom(ByteString data, ExtensionRegistry extensionRegistry) {
IBuilder IBuilder.MergeFrom(ByteString data, ExtensionRegistry extensionRegistry) {
CodedInputStream input = data.CreateCodedInput();
MergeFrom(input, extensionRegistry);
((IBuilder)this).MergeFrom(input, extensionRegistry);
input.CheckLastTagWas(0);
return this;
}
public IBuilder MergeFrom(byte[] data) {
IBuilder IBuilder.MergeFrom(byte[] data) {
CodedInputStream input = CodedInputStream.CreateInstance(data);
MergeFrom(input);
((IBuilder)this).MergeFrom(input);
input.CheckLastTagWas(0);
return this;
}
public IBuilder MergeFrom(byte[] data, ExtensionRegistry extensionRegistry) {
IBuilder IBuilder.MergeFrom(byte[] data, ExtensionRegistry extensionRegistry) {
CodedInputStream input = CodedInputStream.CreateInstance(data);
MergeFrom(input, extensionRegistry);
((IBuilder)this).MergeFrom(input, extensionRegistry);
input.CheckLastTagWas(0);
return this;
}
public IBuilder MergeFrom(Stream input) {
IBuilder IBuilder.MergeFrom(Stream input) {
CodedInputStream codedInput = CodedInputStream.CreateInstance(input);
MergeFrom(codedInput);
((IBuilder)this).MergeFrom(codedInput);
codedInput.CheckLastTagWas(0);
return this;
}
public IBuilder MergeFrom(Stream input, ExtensionRegistry extensionRegistry) {
IBuilder IBuilder.MergeFrom(Stream input, ExtensionRegistry extensionRegistry) {
CodedInputStream codedInput = CodedInputStream.CreateInstance(input);
MergeFrom(codedInput, extensionRegistry);
((IBuilder) this).MergeFrom(codedInput, extensionRegistry);
codedInput.CheckLastTagWas(0);
return this;
}
......
......@@ -13,11 +13,9 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers {
......@@ -56,7 +54,7 @@ namespace Google.ProtocolBuffers {
}
#endregion
public bool IsInitialized {
public virtual bool IsInitialized {
get {
// Check that all required fields are present.
foreach (FieldDescriptor field in DescriptorForType.Fields) {
......@@ -92,7 +90,7 @@ namespace Google.ProtocolBuffers {
return TextFormat.PrintToString(this);
}
public void WriteTo(CodedOutputStream output) {
public virtual void WriteTo(CodedOutputStream output) {
foreach (KeyValuePair<FieldDescriptor, object> entry in AllFields) {
FieldDescriptor field = entry.Key;
if (field.IsRepeated) {
......@@ -107,14 +105,14 @@ namespace Google.ProtocolBuffers {
}
UnknownFieldSet unknownFields = UnknownFields;
if (DescriptorForType.Options.IsMessageSetWireFormat) {
if (DescriptorForType.Options.MessageSetWireFormat) {
unknownFields.WriteAsMessageSetTo(output);
} else {
unknownFields.WriteTo(output);
}
}
public int SerializedSize {
public virtual int SerializedSize {
get {
int size = memoizedSize;
if (size != -1) {
......@@ -134,7 +132,7 @@ namespace Google.ProtocolBuffers {
}
UnknownFieldSet unknownFields = UnknownFields;
if (DescriptorForType.Options.IsMessageSetWireFormat) {
if (DescriptorForType.Options.MessageSetWireFormat) {
size += unknownFields.SerializedSizeAsMessageSet;
} else {
size += unknownFields.SerializedSize;
......@@ -184,73 +182,5 @@ namespace Google.ProtocolBuffers {
hash = (53 * hash) + AllFields.GetHashCode();
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 {
/// <summary>
/// This only exists until we've got the real code...
/// </summary>
/*
public abstract class TemporaryMessage<T> : IMessage<T> where T : IMessage<T> {
#region IMessage<T> Members
......@@ -84,7 +85,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
}
public partial class MessageOptions : TemporaryMessage<MessageOptions> {
public bool IsMessageSetWireFormat;
public bool MessageSetWireFormat;
}
public partial class DescriptorProto : TemporaryMessage<DescriptorProto> {
......@@ -123,6 +124,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos {
public string FullName { get; set; }
public FileOptions Options { get; set; }
public string Package { get; set; }
}
public partial class FileOptions : TemporaryMessage<FileOptions> { }
......@@ -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 @@
/// </summary>
/// <typeparam name="TOptions">The associated options protocol buffer type</typeparam>
public interface IDescriptorProto<TOptions> {
/// <summary>
/// The fully qualified name of the descriptor's target.
/// </summary>
string FullName { get; }
/// <summary>
/// The brief name of the descriptor's target.
......
......@@ -32,9 +32,10 @@ namespace Google.ProtocolBuffers.Descriptors {
/// <summary>
/// The fully qualified name of the descriptor's target.
/// TODO(jonskeet): Implement!
/// </summary>
public string FullName {
get { return proto.FullName; }
get { return null; }
}
/// <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 {
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) {
}
/// <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 {
internal FieldDescriptor FindFieldByNumber(int fieldNumber) {
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 {
extension.Descriptor.FieldNumber)] = extension;
FieldDescriptor field = extension.Descriptor;
if (field.ContainingType.Options.IsMessageSetWireFormat
if (field.ContainingType.Options.MessageSetWireFormat
&& field.FieldType == FieldType.Message
&& field.IsOptional
&& field.ExtensionScope == field.MessageType) {
......
......@@ -2,9 +2,7 @@
using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers.FieldAccess {
public class FieldAccessorTable<TMessage, TBuilder>
where TMessage : IMessage<TMessage>
where TBuilder : IBuilder<TMessage> {
public class FieldAccessorTable {
readonly MessageDescriptor descriptor;
......@@ -12,11 +10,11 @@ namespace Google.ProtocolBuffers.FieldAccess {
get { return descriptor; }
}
public FieldAccessorTable(MessageDescriptor descriptor, String[] pascalCaseNames) {
public FieldAccessorTable(MessageDescriptor descriptor, String[] pascalCaseFieldNames, Type messageType, Type builderType) {
this.descriptor = descriptor;
}
internal IFieldAccessor<TMessage, TBuilder> this[FieldDescriptor field] {
internal IFieldAccessor this[FieldDescriptor field] {
get { return null; }
}
}
......
......@@ -5,25 +5,23 @@
/// The property descriptors for each field are created once and then cached.
/// In addition, this interface holds knowledge of repeated fields, builders etc.
/// </summary>
internal interface IFieldAccessor<TMessage, TBuilder>
where TMessage : IMessage<TMessage>
where TBuilder : IBuilder<TMessage> {
internal interface IFieldAccessor {
/// <summary>
/// Indicates whether the specified message contains the field.
/// </summary>
bool Has(IMessage<TMessage> message);
bool Has(IMessage message);
/// <summary>
/// Gets the count of the repeated field in the specified message.
/// </summary>
int GetRepeatedCount(IMessage<TMessage> message);
int GetRepeatedCount(IMessage message);
/// <summary>
/// Clears the field in the specified builder.
/// </summary>
/// <param name="builder"></param>
void Clear(IBuilder<TMessage> builder);
void Clear(IBuilder builder);
/// <summary>
/// Creates a builder for the type of this field (which must be a message field).
......@@ -33,27 +31,27 @@
/// <summary>
/// Accessor for single fields
/// </summary>
object GetValue(IMessage<TMessage> message);
object GetValue(IMessage message);
/// <summary>
/// Mutator for single fields
/// </summary>
void SetValue(IBuilder<TMessage> builder, object value);
void SetValue(IBuilder builder, object value);
/// <summary>
/// Accessor for repeated fields
/// </summary>
object GetRepeatedValue(IMessage<TMessage> message, int index);
object GetRepeatedValue(IMessage message, int index);
/// <summary>
/// Mutator for repeated fields
/// </summary>
void SetRepeated(IBuilder<TMessage> builder, int index, object value);
void SetRepeated(IBuilder builder, int index, object value);
/// <summary>
/// Adds the specified value to the field in the given builder.
/// </summary>
void AddRepeated(IBuilder<TMessage> builder, object value);
void AddRepeated(IBuilder builder, object value);
/// <summary>
/// Returns a read-only wrapper around the value of a repeated field.
/// </summary>
object GetRepeatedWrapper(IBuilder<TMessage> builder);
object GetRepeatedWrapper(IBuilder builder);
}
}
......@@ -121,7 +121,7 @@ namespace Google.ProtocolBuffers {
uint tag) {
MessageDescriptor type = builder.DescriptorForType;
if (type.Options.IsMessageSetWireFormat
if (type.Options.MessageSetWireFormat
&& tag == WireFormat.MessageSetTag.ItemStart) {
MergeMessageSetExtensionFromCodedStream(input, unknownFields, extensionRegistry, builder);
return true;
......@@ -524,7 +524,7 @@ namespace Google.ProtocolBuffers {
/// Writes a single field to a CodedOutputStream.
/// </summary>
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);
} else {
if (field.IsRepeated) {
......@@ -548,7 +548,7 @@ namespace Google.ProtocolBuffers {
FieldDescriptor field = entry.Key;
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);
} else {
if (field.IsRepeated) {
......
......@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Text;
using Google.ProtocolBuffers.Collections;
using Google.ProtocolBuffers.Descriptors;
using System.IO;
namespace Google.ProtocolBuffers {
/// <summary>
......@@ -17,7 +18,7 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// Returns the message being built at the moment.
/// </summary>
protected abstract GeneratedMessage<TMessage,TBuilder> MessageBeingBuilt { get; }
protected abstract TMessage MessageBeingBuilt { get; }
public override bool Initialized {
get { return MessageBeingBuilt.IsInitialized; }
......@@ -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 {
get { return MessageBeingBuilt.DescriptorForType; }
}
......@@ -73,8 +97,8 @@ namespace Google.ProtocolBuffers {
get { return DefaultInstanceForType; }
}
protected override IBuilder CreateBuilderForFieldImpl(FieldDescriptor field) {
return CreateBuilderForField(field);
public override IBuilder CreateBuilderForField(FieldDescriptor field) {
return MessageBeingBuilt.InternalFieldAccessors[field].CreateBuilder();
}
protected override IBuilder ClearFieldImpl(FieldDescriptor field) {
......@@ -85,69 +109,78 @@ namespace Google.ProtocolBuffers {
return AddRepeatedField(field, value);
}
public new abstract IBuilder<TMessage> Clear();
public IBuilder<TMessage> MergeFrom(IMessage<TMessage> other) {
throw new NotImplementedException();
public IBuilder<TMessage> ClearField(FieldDescriptor field) {
MessageBeingBuilt.InternalFieldAccessors[field].Clear(this);
return this;
}
public abstract TMessage Build();
public abstract TMessage BuildPartial();
public abstract IBuilder<TMessage> Clone();
IBuilder<TMessage> IBuilder<TMessage>.MergeFrom(CodedInputStream input) {
throw new NotImplementedException();
}
// FIXME: Implement!
public virtual IBuilder<TMessage> MergeFrom(TMessage other) { return this; }
public virtual IBuilder<TMessage> MergeUnknownFields(UnknownFieldSet unknownFields) { return this; }
IBuilder<TMessage> IBuilder<TMessage>.MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry) {
throw new NotImplementedException();
public IBuilder<TMessage> AddRepeatedField(FieldDescriptor field, object value) {
MessageBeingBuilt.InternalFieldAccessors[field].AddRepeated(this, value);
return this;
}
public TMessage DefaultInstanceForType {
get { throw new NotImplementedException(); }
public IBuilder<TMessage> MergeFrom(ByteString data) {
((IBuilder) this).MergeFrom(data);
return this;
}
public IBuilder CreateBuilderForField(FieldDescriptor field) {
throw new NotImplementedException();
public IBuilder<TMessage> MergeFrom(ByteString data, ExtensionRegistry extensionRegistry) {
((IBuilder) this).MergeFrom(data, extensionRegistry);
return this;
}
public IBuilder<TMessage> ClearField(FieldDescriptor field) {
MessageBeingBuilt.InternalFieldAccessors[field].Clear(this);
public IBuilder<TMessage> MergeFrom(byte[] data) {
((IBuilder) this).MergeFrom(data);
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;
}
public new IBuilder<TMessage> MergeUnknownFields(UnknownFieldSet unknownFields) {
throw new NotImplementedException();
public IBuilder<TMessage> MergeFrom(Stream input) {
((IBuilder) this).MergeFrom(input);
return this;
}
IBuilder<TMessage> IBuilder<TMessage>.MergeFrom(ByteString data) {
throw new NotImplementedException();
public IBuilder<TMessage> MergeFrom(Stream input, ExtensionRegistry extensionRegistry) {
((IBuilder) this).MergeFrom(input, extensionRegistry);
return this;
}
IBuilder<TMessage> IBuilder<TMessage>.MergeFrom(ByteString data, ExtensionRegistry extensionRegistry) {
throw new NotImplementedException();
/// <summary>
/// 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();
}
IBuilder<TMessage> IBuilder<TMessage>.MergeFrom(byte[] data) {
throw new NotImplementedException();
return BuildPartial();
}
IBuilder<TMessage> IBuilder<TMessage>.MergeFrom(byte[] data, ExtensionRegistry extensionRegistry) {
throw new NotImplementedException();
/// <summary>
/// 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);
}
IBuilder<TMessage> IBuilder<TMessage>.MergeFrom(System.IO.Stream input) {
throw new NotImplementedException();
return BuildPartial();
}
IBuilder<TMessage> IBuilder<TMessage>.MergeFrom(System.IO.Stream input, ExtensionRegistry extensionRegistry) {
throw new NotImplementedException();
}
public abstract TMessage BuildPartial();
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 {
private readonly UnknownFieldSet unknownFields = UnknownFieldSet.DefaultInstance;
protected internal abstract FieldAccessorTable<TMessage, TBuilder> InternalFieldAccessors { get; }
protected internal abstract FieldAccessorTable InternalFieldAccessors { get; }
public override MessageDescriptor DescriptorForType {
get { return InternalFieldAccessors.Descriptor; }
......@@ -30,13 +30,9 @@ namespace Google.ProtocolBuffers {
return CreateBuilderForType();
}
public IMessage<TMessage> DefaultInstanceForType {
get { throw new NotImplementedException(); }
}
public abstract TMessage DefaultInstanceForType { get; }
public IBuilder<TMessage> CreateBuilderForType() {
throw new NotImplementedException();
}
public abstract IBuilder<TMessage> CreateBuilderForType();
private IDictionary<FieldDescriptor, Object> GetMutableFieldMap() {
......@@ -44,7 +40,7 @@ namespace Google.ProtocolBuffers {
var ret = new SortedList<FieldDescriptor, object>();
MessageDescriptor descriptor = DescriptorForType;
foreach (FieldDescriptor field in descriptor.Fields) {
IFieldAccessor<TMessage, TBuilder> accessor = InternalFieldAccessors[field];
IFieldAccessor accessor = InternalFieldAccessors[field];
if ((field.IsRepeated && accessor.GetRepeatedCount(this) != 0)
|| accessor.Has(this)) {
ret[field] = accessor.GetValue(this);
......
......@@ -125,7 +125,7 @@ namespace Google.ProtocolBuffers {
/// </summary>
/// <param name="other"></param>
/// <returns></returns>
IBuilder<T> MergeFrom(IMessage<T> other);
IBuilder<T> MergeFrom(T other);
/// <summary>
/// Constructs the final message. Once this is called, this Builder instance
......@@ -142,7 +142,6 @@ namespace Google.ProtocolBuffers {
/// Like Build(), but does not throw an exception if the message is missing
/// required fields. Instead, a partial message is returned.
/// </summary>
/// <returns></returns>
new T BuildPartial();
/// <summary>
......
......@@ -179,8 +179,7 @@ namespace Google.ProtocolBuffers {
/// method is an abstract method of IMessage whereas DefaultInstance is
/// a static property of a specific class. They return the same thing.
/// </summary>
new IMessage<T> DefaultInstanceForType { get; }
new T DefaultInstanceForType { get; }
#region Builders
/// <summary>
......
......@@ -24,7 +24,7 @@ namespace Google.ProtocolBuffers {
/// </summary>
public class InvalidProtocolBufferException : IOException {
private InvalidProtocolBufferException(string message)
internal InvalidProtocolBufferException(string message)
: base(message) {
}
......
......@@ -13,7 +13,6 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCopyright("Copyright © 2008")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyKeyFile ("Google.ProtocolBuffers.snk")]
// 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
// COM, set the ComVisible attribute to true on that type.
......
......@@ -12,6 +12,8 @@
<AssemblyName>Google.ProtocolBuffers</AssemblyName>
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>Properties\Google.ProtocolBuffers.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
......@@ -45,10 +47,13 @@
<Compile Include="Collections\Lists.cs" />
<Compile Include="Collections\ReadOnlyDictionary.cs" />
<Compile Include="DescriptorProtos\Autogenerated.cs" />
<Compile Include="DescriptorProtos\DescriptorProtoFile.cs" />
<Compile Include="DescriptorProtos\IDescriptorProto.cs" />
<Compile Include="DescriptorProtos\PartialClasses.cs" />
<Compile Include="Descriptors\DescriptorBase.cs" />
<Compile Include="Descriptors\DescriptorPool.cs" />
<Compile Include="Descriptors\EnumDescriptor.cs" />
<Compile Include="Descriptors\EnumDescriptorIndexAttribute.cs" />
<Compile Include="Descriptors\EnumValueDescriptor.cs" />
<Compile Include="Descriptors\FieldDescriptor.cs" />
<Compile Include="Descriptors\FieldMappingAttribute.cs" />
......@@ -77,6 +82,9 @@
<Compile Include="UnknownFieldSet.cs" />
<Compile Include="WireFormat.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Properties\Google.ProtocolBuffers.snk" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- 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.
......
......@@ -17,5 +17,12 @@ using System;
namespace Google.ProtocolBuffers {
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) {
// TODO(jonskeet): Change CONSTANT_CASE into PascalCase
printer->Print(vars,
"[pb::DescriptorIndex($index$)]\r\n"
"[pbd::EnumDescriptorIndex($index$)]\r\n"
"$name$ = $number$,\r\n");
}
printer->Outdent();
......
......@@ -68,20 +68,25 @@ EnumFieldGenerator::~EnumFieldGenerator() {}
void EnumFieldGenerator::
GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
"private boolean has$capitalized_name$;\r\n"
"private bool has$capitalized_name$;\r\n"
"private $type$ $name$_ = $default$;\r\n"
"public boolean Has$capitalized_name$() { return has$capitalized_name$; }\r\n"
"public $type$ Get$capitalized_name$() { return $name$_; }\r\n");
"public bool Has$capitalized_name$ {\r\n"
" get { return has$capitalized_name$; }\r\n"
"}\r\n"
"public $type$ $capitalized_name$ {"
" get { return $name$_; }"
"}\r\n");
}
void EnumFieldGenerator::
GenerateBuilderMembers(io::Printer* printer) const {
printer->Print(variables_,
"public boolean Has$capitalized_name$() {\r\n"
" return result.Has$capitalized_name$();\r\n"
"public bool Has$capitalized_name$ {\r\n"
" get { return result.Has$capitalized_name$; }\r\n"
"}\r\n"
"public $type$ Get$capitalized_name$() {\r\n"
" return result.Get$capitalized_name$();\r\n"
"public $type$ $capitalized_name$ {\r\n"
" get { return result.$capitalized_name$; }\r\n"
" set { Set$capitalized_name$(value); }\r\n"
"}\r\n"
"public Builder Set$capitalized_name$($type$ value) {\r\n"
" result.has$capitalized_name$ = true;\r\n"
......@@ -98,8 +103,8 @@ GenerateBuilderMembers(io::Printer* printer) const {
void EnumFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_,
"if (other.has$capitalized_name$()) {\r\n"
" set$capitalized_name$(other.get$capitalized_name$());\r\n"
"if (other.Has$capitalized_name$) {\r\n"
" $capitalized_name$ = other.$capitalized_name$;\r\n"
"}\r\n");
}
......@@ -111,36 +116,32 @@ GenerateBuildingCode(io::Printer* printer) const {
void EnumFieldGenerator::
GenerateParsingCode(io::Printer* printer) const {
printer->Print(variables_,
"int rawValue = input.readEnum();\r\n"
"$type$ value = $type$.valueOf(rawValue);\r\n"
"if (value == null) {\r\n"
" unknownFields.mergeVarintField($number$, rawValue);\r\n"
// TODO(jonskeet): Make a more efficient way of doing this
"int rawValue = input.ReadEnum();\r\n"
"if (!global::System.Enum.IsDefined(typeof($type$), rawValue)) {\r\n"
" unknownFields.MergeVarintField($number$, (ulong) rawValue);\r\n"
"} else {\r\n"
" set$capitalized_name$(value);\r\n"
" $capitalized_name$ = ($type$) rawValue;\r\n"
"}\r\n");
}
void EnumFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
printer->Print(variables_,
"if (has$capitalized_name$()) {\r\n"
" output.writeEnum($number$, get$capitalized_name$().getNumber());\r\n"
"if (Has$capitalized_name$) {\r\n"
" output.WriteEnum($number$, (int) $capitalized_name$);\r\n"
"}\r\n");
}
void EnumFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_,
"if (has$capitalized_name$()) {\r\n"
"if (Has$capitalized_name$) {\r\n"
" size += pb::CodedOutputStream\r\n"
" .computeEnumSize($number$, get$capitalized_name$().getNumber());\r\n"
" .ComputeEnumSize($number$, (int) $capitalized_name$);\r\n"
"}\r\n");
}
string EnumFieldGenerator::GetBoxedType() const {
return ClassName(descriptor_->enum_type());
}
// ===================================================================
RepeatedEnumFieldGenerator::
......@@ -154,17 +155,19 @@ RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
void RepeatedEnumFieldGenerator::
GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
"private System.Collections.Generic.List<$type$> $name$_ =\r\n"
" new System.Collections.Generic.List<$type$> ();\r\n"
"public System.Collections.Generic.List<$type$> $capitalized_name$List() {\r\n"
" return $name$_.AsReadOnly ();\r\n" // note: unmodifiable list
"private scg::IList<$type$> $name$_ = new scg::List<$type$> ();\r\n"
"public scg.IList<$type$> $capitalized_name$List {\r\n"
" get { return pbc::Lists.AsReadOnly($name$_); }\r\n" // note: unmodifiable list
"}\r\n"
// Redundant API calls?
//"public int $capitalized_name$Count() { get { return $name$_.Count; } }\r\n"
//"public $type$ get$capitalized_name$(int index) {\r\n"
//" return $name$_.get(index);\r\n"
//"}\r\n"
// TODO(jonskeet): Possibly. Include for portability to start with though.
"public int $capitalized_name$Count {\r\n"
" get { return $name$_.Count; }\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 {
// 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
// immutable.
"public global::System.Collections.Generic::IList<$type$> get$capitalized_name$List() {\r\n"
" return java.util.Collections.unmodifiableList(result.$name$_);\r\n"
"public global::System.Collections.Generic::IList<$type$> $capitalized_name$List {\r\n"
" get { return pbc::Lists.AsReadOnly(result.$name$_); }\r\n"
"}\r\n"
"public int get$capitalized_name$Count() {\r\n"
" return result.get$capitalized_name$Count();\r\n"
"public int $capitalized_name$Count {\r\n"
" get { return result.get$capitalized_name$Count; } \r\n"
"}\r\n"
"public $type$ get$capitalized_name$(int index) {\r\n"
" return result.get$capitalized_name$(index);\r\n"
"public $type$ Get$capitalized_name$(int index) {\r\n"
" return result.Get$capitalized_name$(index);\r\n"
"}\r\n"
"public Builder set$capitalized_name$(int index, $type$ value) {\r\n"
" result.$name$_.set(index, value);\r\n"
"public Builder Set$capitalized_name$(int index, $type$ value) {\r\n"
" result.$name$_[index] = value;\r\n"
" return this;\r\n"
"}\r\n"
"public Builder add$capitalized_name$($type$ value) {\r\n"
" if (result.$name$_.isEmpty()) {\r\n"
" result.$name$_ = new java.util.ArrayList<$type$>();\r\n"
" if (result.$name$_.Count == 0) {\r\n"
" result.$name$_ = new scg::List<$type$>();\r\n"
" }\r\n"
" result.$name$_.add(value);\r\n"
" result.$name$_.Add(value);\r\n"
" return this;\r\n"
"}\r\n"
"public Builder addAll$capitalized_name$<T>(\r\n"
" global::System.Collections.Generic.IEnumerable<T> values) where T : $type$ {\r\n"
" if (result.$name$_.isEmpty()) {\r\n"
" result.$name$_ = new java.util.ArrayList<$type$>();\r\n"
"public Builder AddAll$capitalized_name$(scg::IEnumerable<$type$> values) {\r\n"
" if (result.$name$_.Count == 0) {\r\n"
" result.$name$_ = new scg::List<$type$>();\r\n"
" }\r\n"
" super.addAll(values, result.$name$_);\r\n"
" base.AddRange(values, result.$name$_);\r\n"
" return this;\r\n"
"}\r\n"
"public Builder clear$capitalized_name$() {\r\n"
" result.$name$_ = java.util.Collections.emptyList();\r\n"
"public Builder Clear$capitalized_name$() {\r\n"
" result.$name$_ = pbc::Lists<$type$>.Empty;\r\n"
" return this;\r\n"
"}\r\n");
}
......@@ -212,56 +214,49 @@ GenerateBuilderMembers(io::Printer* printer) const {
void RepeatedEnumFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_,
"if (!other.$name$_.isEmpty()) {\r\n"
" if (result.$name$_.isEmpty()) {\r\n"
" result.$name$_ = new java.util.ArrayList<$type$>();\r\n"
"if (other.$name$_.Count != 0) {\r\n"
" if (result.$name$_.Count == 0) {\r\n"
" result.$name$_ = new scg::List<$type$>();\r\n"
" }\r\n"
" result.$name$_.addAll(other.$name$_);\r\n"
" base.AddRange(other.$name$_, result.$name$_);\r\n"
"}\r\n");
}
void RepeatedEnumFieldGenerator::
GenerateBuildingCode(io::Printer* printer) const {
printer->Print(variables_,
"if (result.$name$_ != java.util.Collections.EMPTY_LIST) {\r\n"
" result.$name$_ =\r\n"
" java.util.Collections.unmodifiableList(result.$name$_);\r\n"
"}\r\n");
"result.$name$_ = pbc::Lists.AsReadOnly(result.$name$_);\r\n");
}
void RepeatedEnumFieldGenerator::
GenerateParsingCode(io::Printer* printer) const {
printer->Print(variables_,
"int rawValue = input.readEnum();\r\n"
"int rawValue = input.ReadEnum();\r\n"
"$type$ value = $type$.valueOf(rawValue);\r\n"
"if (value == null) {\r\n"
" unknownFields.mergeVarintField($number$, rawValue);\r\n"
" unknownFields.MergeVarintField($number$, rawValue);\r\n"
"} else {\r\n"
" add$capitalized_name$(value);\r\n"
" Add$capitalized_name$(value);\r\n"
"}\r\n");
}
void RepeatedEnumFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
printer->Print(variables_,
"for ($type$ element : get$capitalized_name$List()) {\r\n"
" output.writeEnum($number$, element.getNumber());\r\n"
"foreach ($type$ element in $capitalized_name$List) {\r\n"
" output.WriteEnum($number$, element.Number);\r\n"
"}\r\n");
}
void RepeatedEnumFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
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"
" .computeEnumSize($number$, element.getNumber());\r\n"
" .ComputeEnumSize($number$, element.Number);\r\n"
"}\r\n");
}
string RepeatedEnumFieldGenerator::GetBoxedType() const {
return ClassName(descriptor_->enum_type());
}
} // namespace csharp
} // namespace compiler
} // namespace protobuf
......
......@@ -45,8 +45,6 @@ class EnumFieldGenerator : public FieldGenerator {
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;
string GetBoxedType() const;
private:
const FieldDescriptor* descriptor_;
map<string, string> variables_;
......
......@@ -40,17 +40,17 @@ void ExtensionGenerator::Generate(io::Printer* printer) {
vars["containing_type"] = ClassName(descriptor_->containing_type());
vars["index"] = SimpleItoa(descriptor_->index());
JavaType csharp_type = GetJavaType(descriptor_);
MappedType mapped_type = GetMappedType(descriptor_);
string singular_type;
switch (csharp_type) {
case JAVATYPE_MESSAGE:
switch (mapped_type) {
case MAPPEDTYPE_MESSAGE:
vars["type"] = ClassName(descriptor_->message_type());
break;
case JAVATYPE_ENUM:
case MAPPEDTYPE_ENUM:
vars["type"] = ClassName(descriptor_->enum_type());
break;
default:
vars["type"] = BoxedPrimitiveTypeName(csharp_type);
vars["type"] = MappedTypeName(mapped_type);
break;
}
......
......@@ -51,19 +51,19 @@ FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor)
FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field) {
if (field->is_repeated()) {
switch (GetJavaType(field)) {
case JAVATYPE_MESSAGE:
switch (GetMappedType(field)) {
case MAPPEDTYPE_MESSAGE:
return new RepeatedMessageFieldGenerator(field);
case JAVATYPE_ENUM:
case MAPPEDTYPE_ENUM:
return new RepeatedEnumFieldGenerator(field);
default:
return new RepeatedPrimitiveFieldGenerator(field);
}
} else {
switch (GetJavaType(field)) {
case JAVATYPE_MESSAGE:
switch (GetMappedType(field)) {
case MAPPEDTYPE_MESSAGE:
return new MessageFieldGenerator(field);
case JAVATYPE_ENUM:
case MAPPEDTYPE_ENUM:
return new EnumFieldGenerator(field);
default:
return new PrimitiveFieldGenerator(field);
......
......@@ -50,8 +50,6 @@ class FieldGenerator {
virtual void GenerateSerializationCode(io::Printer* printer) const = 0;
virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0;
virtual string GetBoxedType() const = 0;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator);
};
......
......@@ -38,7 +38,7 @@ namespace csharp {
FileGenerator::FileGenerator(const FileDescriptor* file)
: file_(file),
csharp_namespace_(FileJavaPackage(file)),
csharp_namespace_(FileCSharpNamespace(file)),
classname_(FileClassName(file)) {}
FileGenerator::~FileGenerator() {}
......@@ -72,9 +72,9 @@ bool FileGenerator::Validate(string* error) {
": Cannot generate C# output because the file's top-level class name, \"");
error->append(classname_);
error->append(
"\", matches the name of one of the types declared inside it. "
"Please either rename the type or use the csharp_outer_classname "
"option to specify a different outer class name for the .proto file.");
"\", matches the name of one of the message, service or enum types. "
"Please either rename the type or use the csharp_file_classname "
"option to specify a different file-level class name for the .proto file.");
return false;
}
......@@ -88,24 +88,30 @@ void FileGenerator::Generate(io::Printer* printer) {
"// Generated by the protocol buffer compiler. DO NOT EDIT!\r\n"
"\r\n");
// Namespace alias to avoid lines getting horribly long
printer->Print("using pb = global::Google.ProtocolBuffers;\r\n\r\n");
// Namespace aliases to avoid lines getting horribly long
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()) {
printer->Print("using self = global::$selfnamespace$;\r\n\r\n",
"selfnamespace", csharp_namespace_);
printer->Print(
"namespace $namespace$ {\r\n"
"\r\n",
"namespace $namespace$ {\r\n",
"namespace", csharp_namespace_);
printer->Indent();
}
printer->Print("\r\n");
printer->Print(
"public sealed class $classname$ {\r\n"
" private $classname$() {}\r\n",
"classname", classname_);
"$access$ static partial class $classname$ {\r\n\r\n",
"classname", classname_,
"access", ClassAccessLevel(file_));
printer->Indent();
// -----------------------------------------------------------------
printer->Print("#region Descriptor\r\n");
// Embed the descriptor. We simply serialize the entire FileDescriptorProto
// and embed it as a byte array, which is parsed and built into real
// descriptors at initialization time.
......@@ -115,10 +121,10 @@ void FileGenerator::Generate(io::Printer* printer) {
file_proto.SerializeToString(&file_data);
printer->Print(
"public static pb::Descriptors.FileDescriptor Descriptor {\r\n"
"public static pbd::FileDescriptor Descriptor {\r\n"
" get { return descriptor; }\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[] {");
printer->Indent();
printer->Indent();
......@@ -139,7 +145,7 @@ void FileGenerator::Generate(io::Printer* printer) {
}
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++) {
printer->Print(
" $dependency$.getDescriptor(),\r\n",
......@@ -150,36 +156,58 @@ void FileGenerator::Generate(io::Printer* printer) {
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,
// not classes.
printer->Print("#region Extensions\r\n");
for (int i = 0; i < file_->extension_count(); i++) {
ExtensionGenerator(file_->extension(i)).Generate(printer);
}
printer->Print("#endregion\r\n\r\n");
printer->Print("#region Static variables\r\n");
// Static variables.
for (int i = 0; i < file_->message_type_count(); i++) {
// TODO(kenton): Reuse MessageGenerator objects?
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->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()) {
printer->Outdent();
printer->Print("}\r\n");
......@@ -187,12 +215,12 @@ void FileGenerator::Generate(io::Printer* printer) {
}
template<typename GeneratorClass, typename DescriptorClass>
static void GenerateSibling(const string& package_dir,
const string& csharp_namespace,
static void GenerateSibling(const string& csharp_namespace,
const FileDescriptor* file,
const DescriptorClass* descriptor,
OutputDirectory* output_directory,
vector<string>* file_list) {
string filename = package_dir + descriptor->name() + ".cs";
string filename = descriptor->name() + ".cs";
file_list->push_back(filename);
scoped_ptr<io::ZeroCopyOutputStream> output(
......@@ -203,40 +231,62 @@ static void GenerateSibling(const string& package_dir,
"// Generated by the protocol buffer compiler. DO NOT EDIT!\r\n"
"\r\n");
// Namespace alias to avoid lines getting horribly long
printer.Print("using pb = global::Google.ProtocolBuffers;\r\n\r\n");
// Namespace aliases to avoid lines getting horribly long
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()) {
printer.Print("using self = global::$selfnamespace$;\r\n\r\n",
"selfnamespace", csharp_namespace);
printer.Print(
"namespace $namespace$ {\r\n"
"\r\n",
"namespace $namespace$ {\r\n",
"namespace", csharp_namespace);
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);
if (file->options().csharp_nest_classes()) {
printer.Outdent();
printer.Print("}\r\n");
}
if (!csharp_namespace.empty()) {
printer.Outdent();
printer.Print("}\r\n");
}
}
void FileGenerator::GenerateSiblings(const string& package_dir,
OutputDirectory* output_directory,
void FileGenerator::GenerateSiblings(OutputDirectory* output_directory,
vector<string>* file_list) {
if (file_->options().csharp_multiple_files()) {
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),
output_directory, file_list);
}
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),
output_directory, file_list);
}
for (int i = 0; i < file_->service_count(); i++) {
GenerateSibling<ServiceGenerator>(package_dir, csharp_namespace_,
GenerateSibling<ServiceGenerator>(csharp_namespace_,
file_,
file_->service(i),
output_directory, file_list);
}
......
......@@ -56,8 +56,7 @@ class FileGenerator {
// 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
// service type).
void GenerateSiblings(const string& package_dir,
OutputDirectory* output_directory,
void GenerateSiblings(OutputDirectory* output_directory,
vector<string>* file_list);
const string& csharp_namespace() { return csharp_namespace_; }
......
......@@ -93,25 +93,20 @@ bool CSharpGenerator::Generate(const FileDescriptor* file,
return false;
}
string package_dir =
StringReplace(file_generator.csharp_namespace(), ".", "/", true);
if (!package_dir.empty()) package_dir += "/";
vector<string> all_files;
string csharp_filename = package_dir;
csharp_filename += file_generator.classname();
string csharp_filename = file_generator.classname();
csharp_filename += ".cs";
all_files.push_back(csharp_filename);
// Generate main csharp file.
// Generate main C# file.
scoped_ptr<io::ZeroCopyOutputStream> output(
output_directory->Open(csharp_filename));
io::Printer printer(output.get(), '$');
file_generator.Generate(&printer);
// Generate sibling files.
file_generator.GenerateSiblings(package_dir, output_directory, &all_files);
file_generator.GenerateSiblings(output_directory, &all_files);
// Generate output list if requested.
if (!output_list_file.empty()) {
......
......@@ -104,8 +104,8 @@ string StripProto(const string& filename) {
}
string FileClassName(const FileDescriptor* file) {
if (file->options().has_csharp_outer_classname()) {
return file->options().csharp_outer_classname();
if (file->options().has_csharp_file_classname()) {
return file->options().csharp_file_classname();
} else {
string basename;
string::size_type last_slash = file->name().find_last_of('/');
......@@ -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()) {
return file->options().csharp_namespace();
} else {
......@@ -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;
if (file->options().csharp_multiple_files()) {
result = FileJavaPackage(file);
if (!file->options().csharp_nest_classes()) {
result = "";
} else {
result = ClassName(file);
}
if (!result.empty()) {
result += '.';
}
string classname;
if (file->package().empty()) {
result += full_name;
classname = full_name;
} else {
// Strip the proto package from full_name since we've replaced it with
// the Java package.
result += full_name.substr(file->package().size() + 1);
// the C# package.
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 result = FileJavaPackage(descriptor);
if (!result.empty()) result += '.';
result += FileClassName(descriptor);
return result;
string alias = FileCSharpNamespace(descriptor).empty() ? "global::" : "self::";
return alias + FileClassName(descriptor);
}
JavaType GetJavaType(FieldDescriptor::Type field_type) {
MappedType GetMappedType(FieldDescriptor::Type field_type) {
switch (field_type) {
case FieldDescriptor::TYPE_INT32:
case FieldDescriptor::TYPE_UINT32:
case FieldDescriptor::TYPE_SINT32:
case FieldDescriptor::TYPE_FIXED32:
case FieldDescriptor::TYPE_SFIXED32:
return JAVATYPE_INT;
return MAPPEDTYPE_INT;
case FieldDescriptor::TYPE_INT64:
case FieldDescriptor::TYPE_UINT64:
case FieldDescriptor::TYPE_SINT64:
case FieldDescriptor::TYPE_FIXED64:
case FieldDescriptor::TYPE_SFIXED64:
return JAVATYPE_LONG;
return MAPPEDTYPE_LONG;
case FieldDescriptor::TYPE_FLOAT:
return JAVATYPE_FLOAT;
return MAPPEDTYPE_FLOAT;
case FieldDescriptor::TYPE_DOUBLE:
return JAVATYPE_DOUBLE;
return MAPPEDTYPE_DOUBLE;
case FieldDescriptor::TYPE_BOOL:
return JAVATYPE_BOOLEAN;
return MAPPEDTYPE_BOOLEAN;
case FieldDescriptor::TYPE_STRING:
return JAVATYPE_STRING;
return MAPPEDTYPE_STRING;
case FieldDescriptor::TYPE_BYTES:
return JAVATYPE_BYTES;
return MAPPEDTYPE_BYTES;
case FieldDescriptor::TYPE_ENUM:
return JAVATYPE_ENUM;
return MAPPEDTYPE_ENUM;
case FieldDescriptor::TYPE_GROUP:
case FieldDescriptor::TYPE_MESSAGE:
return JAVATYPE_MESSAGE;
return MAPPEDTYPE_MESSAGE;
// No default because we want the compiler to complain if any new
// types are added.
}
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) {
case JAVATYPE_INT : return "int";
case JAVATYPE_LONG : return "long";
case JAVATYPE_FLOAT : return "float";
case JAVATYPE_DOUBLE : return "double";
case JAVATYPE_BOOLEAN: return "bool";
case JAVATYPE_STRING : return "string";
case JAVATYPE_BYTES : return "pb::ByteString";
case JAVATYPE_ENUM : return NULL;
case JAVATYPE_MESSAGE: return NULL;
case MAPPEDTYPE_INT : return "int";
case MAPPEDTYPE_LONG : return "long";
case MAPPEDTYPE_UINT : return "uint";
case MAPPEDTYPE_ULONG : return "ulong";
case MAPPEDTYPE_FLOAT : return "float";
case MAPPEDTYPE_DOUBLE : return "double";
case MAPPEDTYPE_BOOLEAN: return "bool";
case MAPPEDTYPE_STRING : return "string";
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
// JavaTypes are added.
// MappedTypes are added.
}
GOOGLE_LOG(FATAL) << "Can't get here.";
return NULL;
}
const char* ClassAccessLevel(const FileDescriptor* file) {
return file->options().csharp_public_classes() ? "public" : "internal";
}
} // namespace csharp
} // namespace compiler
} // namespace protobuf
......
......@@ -48,52 +48,56 @@ string UnderscoresToCamelCase(const MethodDescriptor* method);
string StripProto(const string& filename);
// 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);
// Returns the file's Java package name.
string FileJavaPackage(const FileDescriptor* file);
// Returns the file's C# namespace.
string FileCSharpNamespace(const FileDescriptor* file);
// 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.
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
// 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) {
return ToJavaName(descriptor->full_name(), descriptor->file());
return ToCSharpName(descriptor->full_name(), descriptor->file());
}
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);
enum JavaType {
JAVATYPE_INT,
JAVATYPE_LONG,
JAVATYPE_FLOAT,
JAVATYPE_DOUBLE,
JAVATYPE_BOOLEAN,
JAVATYPE_STRING,
JAVATYPE_BYTES,
JAVATYPE_ENUM,
JAVATYPE_MESSAGE
enum MappedType {
MAPPEDTYPE_INT,
MAPPEDTYPE_LONG,
MAPPEDTYPE_UINT,
MAPPEDTYPE_ULONG,
MAPPEDTYPE_FLOAT,
MAPPEDTYPE_DOUBLE,
MAPPEDTYPE_BOOLEAN,
MAPPEDTYPE_STRING,
MAPPEDTYPE_BYTES,
MAPPEDTYPE_ENUM,
MAPPEDTYPE_MESSAGE
};
JavaType GetJavaType(FieldDescriptor::Type field_type);
MappedType GetMappedType(FieldDescriptor::Type field_type);
inline JavaType GetJavaType(const FieldDescriptor* field) {
return GetJavaType(field->type());
inline MappedType GetMappedType(const FieldDescriptor* field) {
return GetMappedType(field->type());
}
// Get the fully-qualified class name for a boxed primitive type, e.g.
// "java.lang.Integer" for JAVATYPE_INT. Returns NULL for enum and message
// types.
const char* BoxedPrimitiveTypeName(JavaType type);
// Get the access level for generated classes: public or internal
const char* ClassAccessLevel(const FileDescriptor* file);
// 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 compiler
......
......@@ -45,8 +45,6 @@ class MessageFieldGenerator : public FieldGenerator {
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;
string GetBoxedType() const;
private:
const FieldDescriptor* descriptor_;
map<string, string> variables_;
......
......@@ -45,8 +45,6 @@ class PrimitiveFieldGenerator : public FieldGenerator {
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;
string GetBoxedType() const;
private:
const FieldDescriptor* descriptor_;
map<string, string> variables_;
......@@ -68,8 +66,6 @@ class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;
string GetBoxedType() const;
private:
const FieldDescriptor* descriptor_;
map<string, string> variables_;
......
......@@ -62,12 +62,12 @@ void ServiceGenerator::Generate(io::Printer* printer) {
printer->Print(
"\r\n"
"public static final\r\n"
" pb::Descriptors.ServiceDescriptor\r\n"
" pbd::ServiceDescriptor\r\n"
" getDescriptor() {\r\n"
" return $file$.getDescriptor().getServices().get($index$);\r\n"
"}\r\n"
"public final pb::Descriptors.ServiceDescriptor\r\n"
" getDescriptorForType() {\r\n"
"public final pbd::ServiceDescriptor\r\n"
" DescriptorForType {\r\n"
" return getDescriptor();\r\n"
"}\r\n",
"file", ClassName(descriptor_->file()),
......@@ -87,14 +87,14 @@ void ServiceGenerator::GenerateCallMethod(io::Printer* printer) {
printer->Print(
"\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::Message request,\r\n"
" pb::IMessage request,\r\n"
" pb::RpcCallback<\r\n"
" pb::Message> done) {\r\n"
" if (method.getService() != getDescriptor()) {\r\n"
" throw new java.lang.IllegalArgumentException(\r\n"
" \"Service.callMethod() given method descriptor for wrong \" +\r\n"
" throw new global::System.ArgumentException(\r\n"
" \"Service.CallMethod() given method descriptor for wrong \" +\r\n"
" \"service type.\");\r\n"
" }\r\n"
" switch(method.getIndex()) {\r\n");
......@@ -118,7 +118,7 @@ void ServiceGenerator::GenerateCallMethod(io::Printer* printer) {
printer->Print(
"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();
......@@ -133,14 +133,14 @@ void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which,
io::Printer* printer) {
printer->Print(
"public final pb::Message\r\n"
" get$request_or_response$Prototype(\r\n"
" pb::Descriptors.MethodDescriptor method) {\r\n"
" Get$request_or_response$Prototype(\r\n"
" pbd::MethodDescriptor method) {\r\n"
" if (method.getService() != getDescriptor()) {\r\n"
" throw new java.lang.IllegalArgumentException(\r\n"
" \"Service.get$request_or_response$Prototype() given method \" +\r\n"
" throw new global::System.ArgumentException(\r\n"
" \"Service.Get$request_or_response$Prototype() given method \" +\r\n"
" \"descriptor for wrong service type.\");\r\n"
" }\r\n"
" switch(method.getIndex()) {\r\n",
" switch(method.Index) {\r\n",
"request_or_response", (which == REQUEST) ? "Request" : "Response");
printer->Indent();
printer->Indent();
......@@ -153,12 +153,12 @@ void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which,
(which == REQUEST) ? method->input_type() : method->output_type());
printer->Print(vars,
"case $index$:\r\n"
" return $type$.getDefaultInstance();\r\n");
" return $type$.DefaultInstance;\r\n");
}
printer->Print(
"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();
......@@ -205,14 +205,14 @@ void ServiceGenerator::GenerateStub(io::Printer* printer) {
" $input$ request,\r\n"
" pb::RpcCallback<$output$> done) {\r\n"
" channel.callMethod(\r\n"
" getDescriptor().getMethods().get($index$),\r\n"
" Descriptor.Methods[$index$],\r\n"
" controller,\r\n"
" request,\r\n"
" $output$.getDefaultInstance(),\r\n"
" $output$.DefaultInstance,\r\n"
" pb::RpcUtil.generalizeCallback(\r\n"
" done,\r\n"
" typeof ($output$),\r\n"
" $output$.getDefaultInstance()));\r\n"
" $output$.DefaultInstance));\r\n"
"}\r\n");
}
......
......@@ -28,8 +28,11 @@ package google.protobuf;
option java_package = "com.google.protobuf";
option java_outer_classname = "DescriptorProtos";
option csharp_namespace = "Google.ProtocolBuffers";
option csharp_outer_classname = "DescriptorProtos";
option csharp_namespace = "Google.ProtocolBuffers.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
// algorithms don't work during bootstrapping.
......@@ -223,10 +226,35 @@ message FileOptions {
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_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 {
......
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