diff options
author | Jon Skeet <skeet@pobox.com> | 2008-08-14 20:33:36 +0100 |
---|---|---|
committer | Jon Skeet <skeet@pobox.com> | 2008-08-14 20:33:36 +0100 |
commit | 9f4f0a56b1a87af398d0fd9e9bff87e62609b0f7 (patch) | |
tree | 3a60ec9bf3413638b40fecf5d0abae7f9a54d49d /csharp | |
parent | c0daf107249d95f454d489613de09a4898cefb20 (diff) | |
download | protobuf-9f4f0a56b1a87af398d0fd9e9bff87e62609b0f7.tar.gz protobuf-9f4f0a56b1a87af398d0fd9e9bff87e62609b0f7.tar.bz2 protobuf-9f4f0a56b1a87af398d0fd9e9bff87e62609b0f7.zip |
Descriptor framework skeleton. Somewhat generic to avoid lots of code duplication.
Diffstat (limited to 'csharp')
14 files changed, 382 insertions, 47 deletions
diff --git a/csharp/ProtocolBuffers/Autogenerated.cs b/csharp/ProtocolBuffers/Autogenerated.cs deleted file mode 100644 index e4aee669..00000000 --- a/csharp/ProtocolBuffers/Autogenerated.cs +++ /dev/null @@ -1,15 +0,0 @@ -// This file contains quick hacks to represent code that will be autogenerated. - -namespace Google.ProtocolBuffers { - public class DescriptorProtos { - public class MessageOptions { - public bool IsMessageSetWireFormat; - } - - public class EnumValueDescriptorProto { - } - - public class FieldDescriptorProto { - } - } -} diff --git a/csharp/ProtocolBuffers/DescriptorProtos/Autogenerated.cs b/csharp/ProtocolBuffers/DescriptorProtos/Autogenerated.cs new file mode 100644 index 00000000..79d78632 --- /dev/null +++ b/csharp/ProtocolBuffers/DescriptorProtos/Autogenerated.cs @@ -0,0 +1,147 @@ +// This file contains quick hacks to represent code that will be autogenerated. + +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 + + public IMessage<T> DefaultInstanceForType { + get { throw new System.NotImplementedException(); } + } + + public IBuilder<T> CreateBuilderForType() { + throw new System.NotImplementedException(); + } + + #endregion + + #region IMessage Members + + public Google.ProtocolBuffers.Descriptors.MessageDescriptor DescriptorForType { + get { throw new System.NotImplementedException(); } + } + + public System.Collections.Generic.IDictionary<Google.ProtocolBuffers.Descriptors.FieldDescriptor, object> AllFields { + get { throw new System.NotImplementedException(); } + } + + public bool HasField(Google.ProtocolBuffers.Descriptors.FieldDescriptor field) { + throw new System.NotImplementedException(); + } + + public object this[Google.ProtocolBuffers.Descriptors.FieldDescriptor field] { + get { throw new System.NotImplementedException(); } + } + + public int GetRepeatedFieldCount(Google.ProtocolBuffers.Descriptors.FieldDescriptor field) { + throw new System.NotImplementedException(); + } + + public object this[Google.ProtocolBuffers.Descriptors.FieldDescriptor field, int index] { + get { throw new System.NotImplementedException(); } + } + + public UnknownFieldSet UnknownFields { + get { throw new System.NotImplementedException(); } + } + + public bool IsInitialized { + get { throw new System.NotImplementedException(); } + } + + public void WriteTo(CodedOutputStream output) { + throw new System.NotImplementedException(); + } + + public int SerializedSize { + get { throw new System.NotImplementedException(); } + } + + public ByteString ToByteString() { + throw new System.NotImplementedException(); + } + + public byte[] ToByteArray() { + throw new System.NotImplementedException(); + } + + public void WriteTo(System.IO.Stream output) { + throw new System.NotImplementedException(); + } + + IMessage IMessage.DefaultInstanceForType { + get { throw new System.NotImplementedException(); } + } + + IBuilder IMessage.CreateBuilderForType() { + throw new System.NotImplementedException(); + } + + #endregion + } + + public partial class MessageOptions : TemporaryMessage<MessageOptions> { + public bool IsMessageSetWireFormat; + } + + public partial class DescriptorProto : TemporaryMessage<DescriptorProto> { + public string Name { get; set; } + public string FullName { get; set; } + public MessageOptions Options { get; set; } + } + + public partial class EnumDescriptorProto : TemporaryMessage<EnumDescriptorProto> { + public string Name { get; set; } + public string FullName { get; set; } + public EnumOptions Options { get; set; } + } + + public partial class EnumOptions : TemporaryMessage<EnumOptions> { } + + public partial class EnumValueDescriptorProto : TemporaryMessage<EnumValueDescriptorProto> { + public string Name { get; set; } + public string FullName { get; set; } + public EnumValueOptions Options { get; set; } + } + + public partial class EnumValueOptions : TemporaryMessage <EnumValueOptions> { } + + public partial class FieldDescriptorProto : TemporaryMessage<FieldDescriptorProto> { + public string Name { get; set; } + public string FullName { get; set; } + public FieldOptions Options { get; set; } + + } + + public partial class FieldOptions : TemporaryMessage<FieldOptions> { } + + public partial class FileDescriptorProto : TemporaryMessage<FileDescriptorProto> { + public string Name { get; set; } + public string FullName { get; set; } + public FileOptions Options { get; set; } + + } + + public partial class FileOptions : TemporaryMessage<FileOptions> { } + + public partial class MethodDescriptorProto : TemporaryMessage<MethodDescriptorProto> { + public string Name { get; set; } + public string FullName { get; set; } + public MethodOptions Options { get; set; } + + } + + public partial class MethodOptions : TemporaryMessage<MethodOptions> { } + + public partial class ServiceDescriptorProto : TemporaryMessage<ServiceDescriptorProto> { + public string Name { get; set; } + public string FullName { get; set; } + public ServiceOptions Options { get; set; } + + } + + public partial class ServiceOptions : TemporaryMessage<ServiceOptions> { } +} diff --git a/csharp/ProtocolBuffers/DescriptorProtos/IDescriptorProto.cs b/csharp/ProtocolBuffers/DescriptorProtos/IDescriptorProto.cs new file mode 100644 index 00000000..1bd415ce --- /dev/null +++ b/csharp/ProtocolBuffers/DescriptorProtos/IDescriptorProto.cs @@ -0,0 +1,22 @@ +namespace Google.ProtocolBuffers.DescriptorProtos { + + /// <summary> + /// Interface implemented by all DescriptorProtos. The generator doesn't + /// emit the interface implementation claim, so PartialClasses.cs contains + /// partial class declarations for each of them. + /// </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. + /// </summary> + string Name { get; } + + TOptions Options { get; } + } +} diff --git a/csharp/ProtocolBuffers/DescriptorProtos/PartialClasses.cs b/csharp/ProtocolBuffers/DescriptorProtos/PartialClasses.cs new file mode 100644 index 00000000..46edb7b1 --- /dev/null +++ b/csharp/ProtocolBuffers/DescriptorProtos/PartialClasses.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Text; + +// This class just contains partial classes for each of the +// autogenerated classes, so that they implement +// IDescriptorProto +namespace Google.ProtocolBuffers.DescriptorProtos { + public partial class DescriptorProto : IDescriptorProto<MessageOptions> { } + public partial class EnumDescriptorProto : IDescriptorProto<EnumOptions> { } + public partial class EnumValueDescriptorProto : IDescriptorProto<EnumValueOptions> { } + public partial class FieldDescriptorProto : IDescriptorProto<FieldOptions> { } + public partial class FileDescriptorProto : IDescriptorProto<FileOptions> { } + public partial class MethodDescriptorProto : IDescriptorProto<MethodOptions> { } + public partial class ServiceDescriptorProto : IDescriptorProto<ServiceOptions> { } +} diff --git a/csharp/ProtocolBuffers/Descriptors/DescriptorBase.cs b/csharp/ProtocolBuffers/Descriptors/DescriptorBase.cs new file mode 100644 index 00000000..bb0f32df --- /dev/null +++ b/csharp/ProtocolBuffers/Descriptors/DescriptorBase.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Google.ProtocolBuffers.DescriptorProtos; + +namespace Google.ProtocolBuffers.Descriptors { + /// <summary> + /// Base class for all descriptors, providing common functionality. + /// </summary> + /// <typeparam name="TProto">Type of the protocol buffer form of this descriptor</typeparam> + /// <typeparam name="TOptions">Type of the options protocol buffer for this descriptor</typeparam> + public abstract class DescriptorBase<TProto, TOptions> where TProto : IMessage<TProto>, IDescriptorProto<TOptions> { + + private readonly TProto proto; + private readonly FileDescriptor file; + + protected DescriptorBase(TProto proto, FileDescriptor file) { + this.proto = proto; + this.file = file; + } + + /// <summary> + /// Returns the protocol buffer form of this descriptor + /// </summary> + public TProto Proto { + get { return proto; } + } + + public TOptions Options { + get { return proto.Options; } + } + + /// <summary> + /// The fully qualified name of the descriptor's target. + /// </summary> + public string FullName { + get { return proto.FullName; } + } + + /// <summary> + /// The brief name of the descriptor's target. + /// </summary> + public string Name { + get { return proto.Name; } + } + + /// <value> + /// The file this descriptor was declared in. + /// </value> + public FileDescriptor File { + get { return file; } + } + } +} diff --git a/csharp/ProtocolBuffers/Descriptors/EnumDescriptor.cs b/csharp/ProtocolBuffers/Descriptors/EnumDescriptor.cs index 2d27b1f0..1ebe5a7e 100644 --- a/csharp/ProtocolBuffers/Descriptors/EnumDescriptor.cs +++ b/csharp/ProtocolBuffers/Descriptors/EnumDescriptor.cs @@ -1,6 +1,11 @@ +using Google.ProtocolBuffers.DescriptorProtos; namespace Google.ProtocolBuffers.Descriptors { - public class EnumDescriptor { + public class EnumDescriptor : IndexedDescriptorBase<EnumDescriptorProto, EnumOptions> { + internal EnumDescriptor(EnumDescriptorProto proto, EnumOptions options, FileDescriptor file, int index) + : base(proto, file, index) { + } + internal EnumValueDescriptor FindValueByNumber(int rawValue) { throw new System.NotImplementedException(); } diff --git a/csharp/ProtocolBuffers/Descriptors/EnumValueDescriptor.cs b/csharp/ProtocolBuffers/Descriptors/EnumValueDescriptor.cs index faa83fd4..94bd68bf 100644 --- a/csharp/ProtocolBuffers/Descriptors/EnumValueDescriptor.cs +++ b/csharp/ProtocolBuffers/Descriptors/EnumValueDescriptor.cs @@ -1,17 +1,18 @@ using System; +using Google.ProtocolBuffers.DescriptorProtos; namespace Google.ProtocolBuffers.Descriptors { - public class EnumValueDescriptor { + public class EnumValueDescriptor : IndexedDescriptorBase<EnumValueDescriptorProto, EnumValueOptions> { - internal EnumValueDescriptor(DescriptorProtos.EnumValueDescriptorProto proto, + private readonly EnumDescriptor enumDescriptor; + + internal EnumValueDescriptor(EnumValueDescriptorProto proto, FileDescriptor file, EnumDescriptor parent, - int index) { + int index) : base (proto, file, index) { enumDescriptor = parent; } - private EnumDescriptor enumDescriptor; - public int Number { get { throw new NotImplementedException(); } } diff --git a/csharp/ProtocolBuffers/Descriptors/FieldDescriptor.cs b/csharp/ProtocolBuffers/Descriptors/FieldDescriptor.cs index cd2f19b1..0cfc723d 100644 --- a/csharp/ProtocolBuffers/Descriptors/FieldDescriptor.cs +++ b/csharp/ProtocolBuffers/Descriptors/FieldDescriptor.cs @@ -2,20 +2,23 @@ using System.Collections.Generic; using System.Reflection; using Google.ProtocolBuffers.Collections; +using Google.ProtocolBuffers.DescriptorProtos; namespace Google.ProtocolBuffers.Descriptors { - public class FieldDescriptor { + public class FieldDescriptor : IndexedDescriptorBase<FieldDescriptorProto, FieldOptions> { - private FieldDescriptor(DescriptorProtos.FieldDescriptorProto proto, - FileDescriptor file, - MessageDescriptor parent, - int index, - bool isExtension) { + private readonly EnumDescriptor enumType; + private readonly MessageDescriptor parent; + + internal FieldDescriptor(FieldDescriptorProto proto, + FileDescriptor file, + MessageDescriptor parent, + int index, + bool isExtension) : base(proto, file, index) { enumType = null; + this.parent = parent; } - private EnumDescriptor enumType; - public bool IsRequired { get; set; @@ -30,9 +33,9 @@ namespace Google.ProtocolBuffers.Descriptors { public bool IsExtension { get; set; } - public MessageDescriptor ContainingType { get; set; } - - public string FullName { get; set; } + public MessageDescriptor ContainingType { + get { return parent; } + } public bool IsOptional { get; set; } @@ -61,10 +64,6 @@ namespace Google.ProtocolBuffers.Descriptors { get { throw new NotImplementedException(); } } - public string Name { - get { throw new NotImplementedException(); } - } - /// <summary> /// Immutable mapping from field type to mapped type. Built using the attributes on /// FieldType values. diff --git a/csharp/ProtocolBuffers/Descriptors/FileDescriptor.cs b/csharp/ProtocolBuffers/Descriptors/FileDescriptor.cs index 0aaca886..38038ee0 100644 --- a/csharp/ProtocolBuffers/Descriptors/FileDescriptor.cs +++ b/csharp/ProtocolBuffers/Descriptors/FileDescriptor.cs @@ -1,4 +1,7 @@ -namespace Google.ProtocolBuffers.Descriptors { - class FileDescriptor { +using Google.ProtocolBuffers.DescriptorProtos; +namespace Google.ProtocolBuffers.Descriptors { + public class FileDescriptor : DescriptorBase<FileDescriptorProto, FileOptions> { + public FileDescriptor(FileDescriptorProto proto, FileDescriptor file) : base(proto, file) { + } } } diff --git a/csharp/ProtocolBuffers/Descriptors/IndexedDescriptorBase.cs b/csharp/ProtocolBuffers/Descriptors/IndexedDescriptorBase.cs new file mode 100644 index 00000000..b9452163 --- /dev/null +++ b/csharp/ProtocolBuffers/Descriptors/IndexedDescriptorBase.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Google.ProtocolBuffers.DescriptorProtos; + +namespace Google.ProtocolBuffers.Descriptors { + /// <summary> + /// Base class for descriptors which are also indexed. This is all of them other than + /// <see cref="FileDescriptor" />. + /// </summary> + public abstract class IndexedDescriptorBase<TProto, TOptions> : DescriptorBase<TProto, TOptions> + where TProto : IMessage<TProto>, IDescriptorProto<TOptions> { + + private readonly int index; + + protected IndexedDescriptorBase(TProto proto, FileDescriptor file, int index) + : base(proto, file) { + this.index = index; + } + + /// <value> + /// The index of this descriptor within its parent descriptor. + /// </value> + /// <remarks> + /// TODO(jonskeet): Transcribe appropriately. + /// </remarks> + public int Index { + get { return index; } + } + } +} diff --git a/csharp/ProtocolBuffers/Descriptors/MessageDescriptor.cs b/csharp/ProtocolBuffers/Descriptors/MessageDescriptor.cs index df2972f6..971bc3eb 100644 --- a/csharp/ProtocolBuffers/Descriptors/MessageDescriptor.cs +++ b/csharp/ProtocolBuffers/Descriptors/MessageDescriptor.cs @@ -1,11 +1,13 @@ using System.Collections.Generic; +using Google.ProtocolBuffers.DescriptorProtos; namespace Google.ProtocolBuffers.Descriptors { - public class MessageDescriptor { + public class MessageDescriptor : DescriptorBase<DescriptorProto, MessageOptions> { public IList<FieldDescriptor> Fields; - public DescriptorProtos.MessageOptions Options; - public string FullName; + + internal MessageDescriptor(DescriptorProto proto, FileDescriptor file) : base(proto, file) { + } internal bool IsExtensionNumber(int fieldNumber) { throw new System.NotImplementedException(); diff --git a/csharp/ProtocolBuffers/Descriptors/ServiceDescriptor.cs b/csharp/ProtocolBuffers/Descriptors/ServiceDescriptor.cs new file mode 100644 index 00000000..dbe93f99 --- /dev/null +++ b/csharp/ProtocolBuffers/Descriptors/ServiceDescriptor.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Google.ProtocolBuffers.DescriptorProtos; + +namespace Google.ProtocolBuffers.Descriptors { + public class ServiceDescriptor : IndexedDescriptorBase<ServiceDescriptorProto, ServiceOptions> { + public ServiceDescriptor(ServiceDescriptorProto proto, FileDescriptor file, int index) + : base(proto, file, index) { + } + } +} diff --git a/csharp/ProtocolBuffers/FieldSet.cs b/csharp/ProtocolBuffers/FieldSet.cs index 4ad94417..0bcbca81 100644 --- a/csharp/ProtocolBuffers/FieldSet.cs +++ b/csharp/ProtocolBuffers/FieldSet.cs @@ -84,7 +84,7 @@ namespace Google.ProtocolBuffers { return fields.ContainsKey(field); } - // TODO(jonskeet): Should this be in UnknownFieldSet.Builder really? + // TODO(jonskeet): Should this be in UnknownFieldSet.Builder really? Or CodedInputStream? internal static void MergeFrom(CodedInputStream input, UnknownFieldSet.Builder unknownFields, ExtensionRegistry extensionRegistry, @@ -103,15 +103,15 @@ namespace Google.ProtocolBuffers { } } - // TODO(jonskeet): Should this be in UnknownFieldSet.Builder really? + // TODO(jonskeet): Should this be in UnknownFieldSet.Builder really? Or CodedInputStream? /// <summary> /// Like <see cref="MergeFrom(CodedInputStream, UnknownFieldSet.Builder, ExtensionRegistry, IBuilder)" /> /// but parses a single field. /// </summary> /// <param name="input">The input to read the field from</param> - /// <param name="unknownFields">The set of unknown fields to add the newly-read field to</param> + /// <param name="unknownFields">The set of unknown fields to add the newly-read field to, if it's not a known field</param> /// <param name="extensionRegistry">Registry to use when an extension field is encountered</param> - /// <param name="builder">A builder (???)</param> + /// <param name="builder">Builder to merge field into, if it's a known field</param> /// <param name="tag">The tag, which should already have been read from the input</param> /// <returns>true unless the tag is an end-group tag</returns> internal static bool MergeFieldFrom(CodedInputStream input, @@ -194,7 +194,7 @@ namespace Google.ProtocolBuffers { return true; } - // TODO(jonskeet): Move to UnknownFieldSet.Builder? + // TODO(jonskeet): Should this be in UnknownFieldSet.Builder really? Or CodedInputStream? /// <summary> /// Called by MergeFieldFrom to parse a MessageSet extension. /// </summary> @@ -512,6 +512,59 @@ namespace Google.ProtocolBuffers { } /// <summary> + /// See <see cref="IMessage.WriteTo(CodedOutputStream)" />. + /// </summary> + public void WriteTo(CodedOutputStream output) { + foreach (KeyValuePair<FieldDescriptor, object> entry in fields) { + WriteField(entry.Key, entry.Value, output); + } + } + + /// <summary> + /// Writes a single field to a CodedOutputStream. + /// </summary> + public void WriteField(FieldDescriptor field, Object value, CodedOutputStream output) { + if (field.IsExtension && field.ContainingType.Options.IsMessageSetWireFormat) { + output.WriteMessageSetExtension(field.FieldNumber, (IMessage) value); + } else { + if (field.IsRepeated) { + foreach (object element in (IEnumerable) value) { + output.WriteField(field.FieldType, field.FieldNumber, element); + } + } else { + output.WriteField(field.FieldType, field.FieldNumber, value); + } + } + } + + /// <summary> + /// See <see cref="IMessage.SerializedSize" />. It's up to the caller to + /// cache the resulting size if desired. + /// </summary> + public int SerializedSize { + get { + int size = 0; + foreach (KeyValuePair<FieldDescriptor, object> entry in fields) { + FieldDescriptor field = entry.Key; + object value = entry.Value; + + if (field.IsExtension && field.ContainingType.Options.IsMessageSetWireFormat) { + size += CodedOutputStream.ComputeMessageSetExtensionSize(field.FieldNumber, (IMessage) value); + } else { + if (field.IsRepeated) { + foreach (object element in (IEnumerable) value) { + size += CodedOutputStream.ComputeFieldSize(field.FieldType, field.FieldNumber, element); + } + } else { + size += CodedOutputStream.ComputeFieldSize(field.FieldType, field.FieldNumber, value); + } + } + } + return size; + } + } + + /// <summary> /// Verifies that the given object is of the correct type to be a valid /// value for the given field. /// </summary> diff --git a/csharp/ProtocolBuffers/ProtocolBuffers.csproj b/csharp/ProtocolBuffers/ProtocolBuffers.csproj index d3cd95f6..5f31a9e7 100644 --- a/csharp/ProtocolBuffers/ProtocolBuffers.csproj +++ b/csharp/ProtocolBuffers/ProtocolBuffers.csproj @@ -38,21 +38,26 @@ <ItemGroup> <Compile Include="AbstractBuilder.cs" /> <Compile Include="AbstractMessage.cs" /> - <Compile Include="Autogenerated.cs" /> <Compile Include="ByteString.cs" /> <Compile Include="CodedInputStream.cs" /> <Compile Include="CodedOutputStream.cs" /> <Compile Include="Collections\Dictionaries.cs" /> <Compile Include="Collections\Lists.cs" /> <Compile Include="Collections\ReadOnlyDictionary.cs" /> + <Compile Include="DescriptorProtos\Autogenerated.cs" /> + <Compile Include="DescriptorProtos\IDescriptorProto.cs" /> + <Compile Include="DescriptorProtos\PartialClasses.cs" /> + <Compile Include="Descriptors\DescriptorBase.cs" /> <Compile Include="Descriptors\EnumDescriptor.cs" /> <Compile Include="Descriptors\EnumValueDescriptor.cs" /> <Compile Include="Descriptors\FieldDescriptor.cs" /> <Compile Include="Descriptors\FieldMappingAttribute.cs" /> <Compile Include="Descriptors\FieldType.cs" /> <Compile Include="Descriptors\FileDescriptor.cs" /> + <Compile Include="Descriptors\IndexedDescriptorBase.cs" /> <Compile Include="Descriptors\MappedType.cs" /> <Compile Include="Descriptors\MessageDescriptor.cs" /> + <Compile Include="Descriptors\ServiceDescriptor.cs" /> <Compile Include="ExtensionInfo.cs" /> <Compile Include="ExtensionRegistry.cs" /> <Compile Include="FieldAccess\Delegates.cs" /> |