Commit 621bb698 authored by Jon Skeet's avatar Jon Skeet

Some work on AbstractBuilder, and complete implementation of UnknownField and UnknownFieldSet

parent a7246897
using System;
using System.Collections.Generic;
using System.Text;
using Google.ProtocolBuffers.Descriptors;
using System.Collections;
using System.IO;
namespace Google.ProtocolBuffers {
/// <summary>
/// Implementation of the non-generic IMessage interface as far as possible.
/// </summary>
public abstract class AbstractBuilder : IBuilder {
public bool Initialized {
get { throw new NotImplementedException(); }
}
public IDictionary<FieldDescriptor, object> AllFields {
get { throw new NotImplementedException(); }
}
public object this[FieldDescriptor field] {
get {
throw new NotImplementedException();
}
set {
throw new NotImplementedException();
}
}
public MessageDescriptor DescriptorForType {
get { throw new NotImplementedException(); }
}
public int GetRepeatedFieldCount(FieldDescriptor field) {
throw new NotImplementedException();
}
public object this[FieldDescriptor field, int index] {
get {
throw new NotImplementedException();
}
set {
throw new NotImplementedException();
}
}
public bool HasField(FieldDescriptor field) {
throw new NotImplementedException();
}
public IBuilder Clear() {
foreach(FieldDescriptor field in AllFields.Keys) {
ClearField(field);
}
return this;
}
public IBuilder MergeFrom(IMessage other) {
if (other.DescriptorForType != DescriptorForType) {
throw new ArgumentException("MergeFrom(Message) can only merge messages of the same type.");
}
// Note: We don't attempt to verify that other's fields have valid
// types. Doing so would be a losing battle. We'd have to verify
// all sub-messages as well, and we'd have to make copies of all of
// them to insure that they don't change after verification (since
// the Message interface itself cannot enforce immutability of
// implementations).
// TODO(jonskeet): Provide a function somewhere called makeDeepCopy()
// which allows people to make secure deep copies of messages.
foreach (KeyValuePair<FieldDescriptor, object> entry in AllFields) {
FieldDescriptor field = entry.Key;
if (field.IsRepeated) {
// Concatenate repeated fields
foreach (object element in (IEnumerable) entry.Value) {
AddRepeatedField(field, element);
}
} else if (field.MappedType == MappedType.Message) {
// Merge singular messages
IMessage existingValue = (IMessage) this[field];
if (existingValue == existingValue.DefaultInstanceForType) {
this[field] = entry.Value;
} else {
this[field] = existingValue.CreateBuilderForType()
.MergeFrom(existingValue)
.MergeFrom((IMessage) entry.Value)
.Build();
}
} else {
// Overwrite simple values
this[field] = entry.Value;
}
}
return this;
}
public IMessage Build() {
throw new NotImplementedException();
}
public IMessage BuildPartial() {
throw new NotImplementedException();
}
public IBuilder Clone() {
throw new NotImplementedException();
}
public IBuilder MergeFrom(CodedInputStream input) {
return MergeFrom(input, ExtensionRegistry.Empty);
}
public IBuilder MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry) {
UnknownFieldSet.Builder unknownFields = UnknownFieldSet.CreateBuilder(UnknownFields);
FieldSet.MergeFrom(input, unknownFields, extensionRegistry, this);
UnknownFields = unknownFields.Build();
return this;
}
public IMessage DefaultInstanceForType {
get { throw new NotImplementedException(); }
}
public IBuilder NewBuilderForField<TField>(FieldDescriptor field) {
throw new NotImplementedException();
}
public IBuilder ClearField(FieldDescriptor field) {
throw new NotImplementedException();
}
public IBuilder AddRepeatedField(FieldDescriptor field, object value) {
throw new NotImplementedException();
}
public IBuilder MergeUnknownFields(UnknownFieldSet unknownFields) {
UnknownFields = UnknownFieldSet.CreateBuilder(UnknownFields)
.MergeFrom(unknownFields)
.Build();
return this;
}
public UnknownFieldSet UnknownFields {
get {
throw new NotImplementedException();
}
set {
throw new NotImplementedException();
}
}
public IBuilder MergeFrom(ByteString data) {
CodedInputStream input = data.CreateCodedInput();
MergeFrom(input);
input.CheckLastTagWas(0);
return this;
}
public IBuilder MergeFrom(ByteString data, ExtensionRegistry extensionRegistry) {
CodedInputStream input = data.CreateCodedInput();
MergeFrom(input, extensionRegistry);
input.CheckLastTagWas(0);
return this;
}
public IBuilder MergeFrom(byte[] data) {
CodedInputStream input = CodedInputStream.CreateInstance(data);
MergeFrom(input);
input.CheckLastTagWas(0);
return this;
}
public IBuilder MergeFrom(byte[] data, ExtensionRegistry extensionRegistry) {
CodedInputStream input = CodedInputStream.CreateInstance(data);
MergeFrom(input, extensionRegistry);
input.CheckLastTagWas(0);
return this;
}
public IBuilder MergeFrom(Stream input) {
CodedInputStream codedInput = CodedInputStream.CreateInstance(input);
MergeFrom(codedInput);
codedInput.CheckLastTagWas(0);
return this;
}
public IBuilder MergeFrom(Stream input, ExtensionRegistry extensionRegistry) {
CodedInputStream codedInput = CodedInputStream.CreateInstance(input);
MergeFrom(codedInput, extensionRegistry);
codedInput.CheckLastTagWas(0);
return this;
}
}
}
......@@ -34,13 +34,15 @@ namespace Google.ProtocolBuffers {
#region Unimplemented members of IMessage
public abstract MessageDescriptor DescriptorForType { get; }
public abstract IDictionary<Descriptors.FieldDescriptor, object> AllFields { get; }
public abstract bool HasField(Descriptors.FieldDescriptor field);
public abstract object this[Descriptors.FieldDescriptor field] { get; }
public abstract int GetRepeatedFieldCount(Descriptors.FieldDescriptor field);
public abstract object this[Descriptors.FieldDescriptor field, int index] { get; }
public abstract IDictionary<FieldDescriptor, object> AllFields { get; }
public abstract bool HasField(FieldDescriptor field);
public abstract object this[FieldDescriptor field] { get; }
public abstract int GetRepeatedFieldCount(FieldDescriptor field);
public abstract object this[FieldDescriptor field, int index] { get; }
public abstract UnknownFieldSet UnknownFields { get; }
public abstract IMessage DefaultInstanceForType { get; }
// FIXME
IMessage IMessage.DefaultInstanceForType { get { return null; } }
IBuilder IMessage.CreateBuilderForType() { return null; }
#endregion
public bool IsInitialized {
......@@ -152,8 +154,6 @@ namespace Google.ProtocolBuffers {
codedOutput.Flush();
}
public abstract IBuilder CreateBuilderForType();
public override bool Equals(object other) {
if (other == this) {
return true;
......@@ -173,5 +173,73 @@ 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
}
}
......@@ -105,6 +105,15 @@ namespace Google.ProtocolBuffers {
return ToString(Encoding.UTF8);
}
/// <summary>
/// Creates a CodedInputStream from this ByteString's data.
/// </summary>
public CodedInputStream CreateCodedInput() {
// We trust CodedInputStream not to reveal the provided byte array or modify it
return CodedInputStream.CreateInstance(bytes);
}
// TODO(jonskeet): CopyTo, Equals, GetHashCode if they turn out to be required
/// <summary>
......
......@@ -321,7 +321,7 @@ namespace Google.ProtocolBuffers {
/// Reads a field of any primitive type. Enums, groups and embedded
/// messages are not handled by this method.
/// </summary>
public object readPrimitiveField(FieldType fieldType) {
public object ReadPrimitiveField(FieldType fieldType) {
switch (fieldType) {
case FieldType.Double: return ReadDouble();
case FieldType.Float: return ReadFloat();
......
......@@ -271,7 +271,7 @@ namespace Google.ProtocolBuffers {
case FieldType.SFixed64: WriteSFixed64(fieldNumber, (long)value); break;
case FieldType.SInt32: WriteSInt32(fieldNumber, (int)value); break;
case FieldType.SInt64: WriteSInt64(fieldNumber, (long)value); break;
case FieldType.Enum: WriteEnum(fieldNumber, ((Descriptors.EnumValueDescriptor)value).Number);
case FieldType.Enum: WriteEnum(fieldNumber, ((EnumValueDescriptor)value).Number);
break;
}
}
......@@ -615,7 +615,7 @@ namespace Google.ProtocolBuffers {
* @param number The field's number.
* @param value Object representing the field's value. Must be of the exact
* type which would be returned by
* {@link Message#getField(Descriptors.FieldDescriptor)} for
* {@link Message#getField(FieldDescriptor)} for
* this field.
*/
public static int ComputeFieldSize(FieldType fieldType, int fieldNumber, Object value) {
......@@ -637,7 +637,7 @@ namespace Google.ProtocolBuffers {
case FieldType.SFixed64: return ComputeSFixed64Size(fieldNumber, (long)value);
case FieldType.SInt32: return ComputeSInt32Size(fieldNumber, (int)value);
case FieldType.SInt64: return ComputeSInt64Size(fieldNumber, (long)value);
case FieldType.Enum: return ComputeEnumSize(fieldNumber, ((Descriptors.EnumValueDescriptor)value).Number);
case FieldType.Enum: return ComputeEnumSize(fieldNumber, ((EnumValueDescriptor)value).Number);
default:
throw new ArgumentOutOfRangeException("Invalid field type " + fieldType);
}
......
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
namespace Google.ProtocolBuffers.Collections {
/// <summary>
/// Utilities class for dealing with lists.
/// </summary>
static class Lists<T> {
static readonly ReadOnlyCollection<T> empty = new ReadOnlyCollection<T>(new T[0]);
/// <summary>
/// Returns an immutable empty list.
/// </summary>
internal static ReadOnlyCollection<T> Empty {
get { return empty; }
}
}
}
......@@ -13,5 +13,17 @@ namespace Google.ProtocolBuffers.Descriptors {
public FieldType FieldType { get; set; }
public int FieldNumber { get; set; }
public bool IsExtension { get; set; }
public MessageDescriptor ContainingType { get; set; }
public string FullName { get; set; }
public bool IsOptional { get; set; }
public MessageDescriptor MessageType { get; set; }
public MessageDescriptor ExtensionScope { get; set; }
}
}
......@@ -7,6 +7,14 @@ namespace Google.ProtocolBuffers.Descriptors {
/// Type as it's mapped onto a .NET type.
/// </summary>
public enum MappedType {
Message
Int32,
Int64,
Single,
Double,
Boolean,
String,
ByteString,
Message,
Enum
}
}
......@@ -5,5 +5,6 @@ namespace Google.ProtocolBuffers.Descriptors {
public class MessageDescriptor {
public IList<FieldDescriptor> Fields;
public DescriptorProtos.MessageOptions Options;
public string FullName;
}
}
using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers
{
public sealed class ExtensionInfo {
/// <summary>
/// The extension's descriptor
/// </summary>
public FieldDescriptor Descriptor { get; private set; }
/// <summary>
/// A default instance of the extensions's type, if it has a message type,
/// or null otherwise.
/// </summary>
public IMessage DefaultInstance { get; private set; }
internal ExtensionInfo(FieldDescriptor descriptor) : this(descriptor, null) {
}
internal ExtensionInfo(FieldDescriptor descriptor, IMessage defaultInstance) {
Descriptor = descriptor;
DefaultInstance = defaultInstance;
}
}
}
\ No newline at end of file
......@@ -13,7 +13,167 @@
// 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.Collections.Generic;
using Google.ProtocolBuffers.Descriptors;
using System;
namespace Google.ProtocolBuffers {
public class ExtensionRegistry {
/// <summary>
/// TODO(jonskeet): Copy docs from Java
/// </summary>
public sealed class ExtensionRegistry {
private static readonly ExtensionRegistry empty = new ExtensionRegistry(
new Dictionary<string, ExtensionInfo>(),
new Dictionary<DescriptorIntPair, ExtensionInfo>(),
true);
private readonly IDictionary<string, ExtensionInfo> extensionsByName;
private readonly IDictionary<DescriptorIntPair, ExtensionInfo> extensionsByNumber;
private readonly bool readOnly;
private ExtensionRegistry(IDictionary<String, ExtensionInfo> extensionsByName,
IDictionary<DescriptorIntPair, ExtensionInfo> extensionsByNumber,
bool readOnly) {
this.extensionsByName = extensionsByName;
this.extensionsByNumber = extensionsByNumber;
this.readOnly = readOnly;
}
/// <summary>
/// Construct a new, empty instance.
/// </summary>
public static ExtensionRegistry CreateInstance() {
return new ExtensionRegistry(new Dictionary<string, ExtensionInfo>(),
new Dictionary<DescriptorIntPair, ExtensionInfo>(), false);
}
/// <summary>
/// Get the unmodifiable singleton empty instance.
/// </summary>
public static ExtensionRegistry Empty {
get { return empty; }
}
public ExtensionRegistry AsReadOnly() {
return new ExtensionRegistry(extensionsByName, extensionsByNumber, true);
}
/// <summary>
/// Finds an extension by fully-qualified field name, in the
/// proto namespace, i.e. result.Descriptor.FullName will match
/// <paramref name="fullName"/> if a match is found. A null
/// reference is returned if the extension can't be found.
/// </summary>
public ExtensionInfo this[string fullName] {
get {
ExtensionInfo ret;
extensionsByName.TryGetValue(fullName, out ret);
return ret;
}
}
/// <summary>
/// Finds an extension by containing type and field number.
/// A null reference is returned if the extension can't be found.
/// </summary>
public ExtensionInfo this[MessageDescriptor containingType, int fieldNumber] {
get {
ExtensionInfo ret;
extensionsByNumber.TryGetValue(new DescriptorIntPair(containingType, fieldNumber), out ret);
return ret;
}
}
/// <summary>
/// Add an extension from a generated file to the registry.
/// </summary>
public void Add<TContainer, TExtension> (GeneratedExtension<TContainer, TExtension> extension)
where TContainer : IMessage<TContainer> {
if (extension.Descriptor.MappedType == MappedType.Message) {
Add(new ExtensionInfo(extension.Descriptor, extension.MessageDefaultInstance));
} else {
Add(new ExtensionInfo(extension.Descriptor, null));
}
}
/// <summary>
/// Adds a non-message-type extension to the registry by descriptor.
/// </summary>
/// <param name="type"></param>
public void Add(FieldDescriptor type) {
if (type.MappedType == MappedType.Message) {
throw new ArgumentException("ExtensionRegistry.Add() must be provided a default instance "
+ "when adding an embedded message extension.");
}
Add(new ExtensionInfo(type, null));
}
/// <summary>
/// Adds a message-type-extension to the registry by descriptor.
/// </summary>
/// <param name="type"></param>
/// <param name="defaultInstance"></param>
public void Add(FieldDescriptor type, IMessage defaultInstance) {
if (type.MappedType != MappedType.Message) {
throw new ArgumentException("ExtensionRegistry.Add() provided a default instance for a "
+ "non-message extension.");
}
Add(new ExtensionInfo(type, defaultInstance));
}
private void Add(ExtensionInfo extension) {
if (readOnly) {
throw new InvalidOperationException("Cannot add entries to a read-only extension registry");
}
if (!extension.Descriptor.IsExtension) {
throw new ArgumentException("ExtensionRegistry.add() was given a FieldDescriptor for a "
+ "regular (non-extension) field.");
}
extensionsByName[extension.Descriptor.FullName] = extension;
extensionsByNumber[new DescriptorIntPair(extension.Descriptor.ContainingType,
extension.Descriptor.FieldNumber)] = extension;
FieldDescriptor field = extension.Descriptor;
if (field.ContainingType.Options.IsMessageSetWireFormat
&& field.FieldType == FieldType.Message
&& field.IsOptional
&& field.ExtensionScope == field.MessageType) {
// This is an extension of a MessageSet type defined within the extension
// type's own scope. For backwards-compatibility, allow it to be looked
// up by type name.
extensionsByName[field.MessageType.FullName] = extension;
}
}
/// <summary>
/// Nested type just used to represent a pair of MessageDescriptor and int, as
/// the key into the "by number" map.
/// </summary>
private struct DescriptorIntPair : IEquatable<DescriptorIntPair> {
readonly MessageDescriptor descriptor;
readonly int number;
internal DescriptorIntPair(MessageDescriptor descriptor, int number) {
this.descriptor = descriptor;
this.number = number;
}
public override int GetHashCode() {
return descriptor.GetHashCode() * ((1 << 16) - 1) + number;
}
public override bool Equals(object obj) {
if (!(obj is DescriptorIntPair)) {
return false;
}
return Equals((DescriptorIntPair)obj);
}
public bool Equals(DescriptorIntPair other) {
return descriptor == other.descriptor && number == other.number;
}
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace Google.ProtocolBuffers.FieldAccess {
/// <summary>
/// Declarations of delegate types used for field access. Can't
/// use Func and Action (other than one parameter) as we can't guarantee .NET 3.5.
/// </summary>
delegate bool HasFunction<TMessage>(TMessage message);
}
using System;
using System.Collections.Generic;
using System.Text;
using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers.FieldAccess {
public class FieldAccessorTable<TMessage, TBuilder>
where TMessage : IMessage<TMessage>
where TBuilder : IBuilder<TMessage> {
readonly MessageDescriptor descriptor;
public MessageDescriptor Descriptor {
get { return descriptor; }
}
public FieldAccessorTable(MessageDescriptor descriptor, String[] pascalCaseNames) {
this.descriptor = descriptor;
}
internal IFieldAccessor<TMessage, TBuilder> this[FieldDescriptor field] {
get { return null; }
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace Google.ProtocolBuffers.FieldAccess {
internal interface IFieldAccessor<TMessage, TBuilder>
where TMessage : IMessage<TMessage>
where TBuilder : IBuilder<TMessage> {
void AddRepeated(IBuilder<TMessage> builder, object value);
bool Has(IMessage<TMessage> message);
int GetRepeatedCount(IMessage<TMessage> message);
void Clear(TBuilder builder);
TBuilder CreateBuilder();
/// <summary>
/// Accessor for single fields
/// </summary>
object this[IMessage<TMessage> message] { get; }
/// <summary>
/// Mutator for single fields
/// </summary>
object this[IBuilder<TMessage> builder] { set; }
/// <summary>
/// Accessor for repeated fields
/// </summary>
object this[IMessage<TMessage> message, int index] { get; }
/// <summary>
/// Mutator for repeated fields
/// </summary>
object this[IBuilder<TMessage> builder, int index] { set; }
}
}
using System;
using System.Collections.Generic;
using System.Text;
using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers.FieldAccess {
internal class SingularFieldAccessor<TMessage, TBuilder> : IFieldAccessor<TMessage, TBuilder>
where TMessage : IMessage<TMessage>
where TBuilder : IBuilder<TMessage> {
readonly HasFunction<TMessage> hasProxy;
readonly Action<TBuilder> clearProxy;
internal SingularFieldAccessor(FieldDescriptor descriptor, String pascalCaseName) {
/* Class<? extends GeneratedMessage> messageClass,
Class<? extends GeneratedMessage.Builder> builderClass) {
getMethod = getMethodOrDie(messageClass, "get" + camelCaseName);
type = getMethod.getReturnType();
setMethod = getMethodOrDie(builderClass, "set" + camelCaseName, type);
hasMethod =
getMethodOrDie(messageClass, "has" + camelCaseName);
clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName); */
}
public bool Has(IMessage<TMessage> message) {
return false;// hasProxy(message);
}
public void Clear(TBuilder builder) {
// clearProxy(builder);
}
public TBuilder CreateBuilder() {
// return createBuilderProxy(builder);
return default(TBuilder);
}
public object this[IMessage<TMessage> message] {
get { return null;/* getProxy(message);*/ }
}
public object this[IBuilder<TMessage> builder] {
set { /*setProxy(builder, value);*/ }
}
#region Repeated operations (which just throw an exception)
public object this[IMessage<TMessage> message, int index] {
get { throw new InvalidOperationException("Repeated operation called on singular field"); }
}
public object this[IBuilder<TMessage> builder, int index] {
set { throw new InvalidOperationException("Repeated operation called on singular field"); }
}
public int GetRepeatedCount(IMessage<TMessage> message) {
throw new InvalidOperationException("Repeated operation called on singular field");
}
public void AddRepeated(IBuilder<TMessage> builder, object value) {
throw new InvalidOperationException("Repeated operation called on singular field");
}
#endregion
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace Google.ProtocolBuffers {
public class FieldSet {
public static void MergeFrom(CodedInputStream input,
UnknownFieldSet.Builder unknownFields,
ExtensionRegistry extensionRegistry,
IBuilder builder) {
while (true) {
uint tag = input.ReadTag();
if (tag == 0) {
break;
}
if (!MergeFieldFrom(input, unknownFields, extensionRegistry,
builder, tag)) {
// end group tag
break;
}
}
}
public static bool MergeFieldFrom(CodedInputStream input,
UnknownFieldSet.Builder unknownFields,
ExtensionRegistry extensionRegistry,
IBuilder builder,
uint tag) {
throw new NotImplementedException();
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using Google.ProtocolBuffers.Descriptors;
namespace Google.ProtocolBuffers {
/// <summary>
/// Base class for all generated extensions.
/// </summary>
/// <remarks>
/// The protocol compiler generates a static singleton instance of this
/// class for each extension. For exmaple, imagine a .proto file with:
/// <code>
/// message Foo {
/// extensions 1000 to max
/// }
///
/// extend Foo {
/// optional int32 bar;
/// }
/// </code>
/// Then MyProto.Foo.Bar has type GeneratedExtension&lt;MyProto.Foo,int&gt;.
/// <para />
/// In general, users should ignore the details of this type, and
/// simply use the static singletons as parmaeters to the extension accessors
/// in ExtendableMessage and ExtendableBuilder.
/// </remarks>
public class GeneratedExtension<TContainer, TExtension> where TContainer : IMessage<TContainer> {
public FieldDescriptor Descriptor;
public IMessage MessageDefaultInstance;
}
}
using System;
using System.Collections.Generic;
using System.Text;
using Google.ProtocolBuffers.Descriptors;
using Google.ProtocolBuffers.FieldAccess;
namespace Google.ProtocolBuffers {
/// <summary>
/// All generated protocol message classes extend this class. It implements
/// most of the IMessage and IBuilder interfaces using reflection. Users
/// can ignore this class as an implementation detail.
/// </summary>
public abstract class GeneratedMessage<TMessage, TBuilder> : AbstractMessage, IMessage<TMessage>
where TMessage : GeneratedMessage<TMessage, TBuilder> where TBuilder : IBuilder<TMessage> {
private readonly UnknownFieldSet unknownFields = UnknownFieldSet.DefaultInstance;
protected abstract FieldAccessorTable<TMessage, TBuilder> InternalFieldAccessors { get; }
public override MessageDescriptor DescriptorForType {
get { return InternalFieldAccessors.Descriptor; }
}
public IMessage<TMessage> DefaultInstanceForType {
get { throw new System.NotImplementedException(); }
}
public IBuilder<TMessage> CreateBuilderForType() {
throw new System.NotImplementedException();
}
private IDictionary<FieldDescriptor, Object> GetMutableFieldMap() {
var ret = new Dictionary<FieldDescriptor, object>();
MessageDescriptor descriptor = DescriptorForType;
foreach (FieldDescriptor field in descriptor.Fields) {
IFieldAccessor<TMessage, TBuilder> accessor = InternalFieldAccessors[field];
if ((field.IsRepeated && accessor.GetRepeatedCount(this) != 0)
|| accessor.Has(this)) {
ret[field] = accessor[this];
}
}
return ret;
}
public override IDictionary<FieldDescriptor, object> AllFields {
// FIXME: Make it immutable
get { return GetMutableFieldMap(); }
}
public override bool HasField(FieldDescriptor field) {
return InternalFieldAccessors[field].Has(this);
}
public override int GetRepeatedFieldCount(FieldDescriptor field) {
return InternalFieldAccessors[field].GetRepeatedCount(this);
}
public override object this[FieldDescriptor field, int index] {
get { return InternalFieldAccessors[field][this, index]; }
}
public override object this[FieldDescriptor field] {
get { return InternalFieldAccessors[field][this]; }
}
public override UnknownFieldSet UnknownFields {
get { return unknownFields; }
}
}
}
......@@ -29,7 +29,6 @@ namespace Google.ProtocolBuffers {
/// how IEnumerable and IEnumerable&lt;T&gt; work.
/// </summary>
public interface IBuilder {
IBuilder MergeFrom(CodedInputStream codedInputStream, ExtensionRegistry extensionRegistry);
/// <summary>
/// Returns true iff all required fields in the message and all
/// embedded messages are set.
......@@ -41,15 +40,15 @@ namespace Google.ProtocolBuffers {
/// The returned map may or may not reflect future changes to the builder.
/// Either way, the returned map is unmodifiable.
/// </summary>
IDictionary<ProtocolBuffers.Descriptors.FieldDescriptor, object> AllFields { get; }
IDictionary<FieldDescriptor, object> AllFields { get; }
/// <summary>
/// Allows getting and setting of a field.
/// <see cref="IMessage{T}.Item(Descriptors.FieldDescriptor)"/>
/// <see cref="IMessage{T}.Item(FieldDescriptor)"/>
/// </summary>
/// <param name="field"></param>
/// <returns></returns>
object this[Descriptors.FieldDescriptor field] { get; set; }
object this[FieldDescriptor field] { get; set; }
/// <summary>
/// Get the message's type's descriptor.
......@@ -62,18 +61,44 @@ namespace Google.ProtocolBuffers {
/// </summary>
/// <param name="field"></param>
/// <returns></returns>
int GetRepeatedFieldCount(Descriptors.FieldDescriptor field);
int GetRepeatedFieldCount(FieldDescriptor field);
/// <summary>
/// Allows getting and setting of a repeated field value.
/// <see cref="IMessage{T}.Item(Descriptors.FieldDescriptor, int)"/>
/// <see cref="IMessage{T}.Item(FieldDescriptor, int)"/>
/// </summary>
object this[Descriptors.FieldDescriptor field, int index] { get; set; }
object this[FieldDescriptor field, int index] { get; set; }
/// <summary>
/// <see cref="IMessage{T}.HasField"/>
/// </summary>
bool HasField(Descriptors.FieldDescriptor field);
bool HasField(FieldDescriptor field);
/// <summary>
/// <see cref="IMessage{T}.UnknownFields"/>
/// </summary>
UnknownFieldSet UnknownFields { get; set; }
#region Non-generic versions of generic methods in IBuilder<T>
IBuilder Clear();
IBuilder MergeFrom(IMessage other);
IMessage Build();
IMessage BuildPartial();
IBuilder Clone();
IBuilder MergeFrom(CodedInputStream input);
IBuilder MergeFrom(CodedInputStream codedInputStream, ExtensionRegistry extensionRegistry);
IMessage DefaultInstanceForType { get; }
IBuilder NewBuilderForField<TField>(FieldDescriptor field);
IBuilder ClearField(FieldDescriptor field);
IBuilder AddRepeatedField(FieldDescriptor field, object value);
IBuilder MergeUnknownFields(UnknownFieldSet unknownFields);
IBuilder MergeFrom(ByteString data);
IBuilder MergeFrom(ByteString data, ExtensionRegistry extensionRegistry);
IBuilder MergeFrom(byte[] data);
IBuilder MergeFrom(byte[] data, ExtensionRegistry extensionRegistry);
IBuilder MergeFrom(Stream input);
IBuilder MergeFrom(Stream input, ExtensionRegistry extensionRegistry);
#endregion
}
/// <summary>
......@@ -85,7 +110,7 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// Resets all fields to their default values.
/// </summary>
IBuilder<T> Clear();
new IBuilder<T> Clear();
/// <summary>
/// Merge the specified other message into the message being
......@@ -111,20 +136,20 @@ namespace Google.ProtocolBuffers {
/// <exception cref="UninitializedMessageException">the message
/// is missing one or more required fields; use BuildPartial to bypass
/// this check</exception>
IMessage<T> Build();
new IMessage<T> Build();
/// <summary>
/// Like Build(), but does not throw an exception if the message is missing
/// required fields. Instead, a partial message is returned.
/// </summary>
/// <returns></returns>
IMessage<T> BuildPartial();
new IMessage<T> BuildPartial();
/// <summary>
/// Clones this builder.
/// TODO(jonskeet): Explain depth of clone.
/// </summary>
IBuilder<T> Clone();
new IBuilder<T> Clone();
/// <summary>
/// Parses a message of this type from the input and merges it with this
......@@ -145,7 +170,7 @@ namespace Google.ProtocolBuffers {
/// Use BuildPartial to build, which ignores missing required fields.
/// </list>
/// </remarks>
IBuilder<T> MergeFrom(CodedInputStream input);
new IBuilder<T> MergeFrom(CodedInputStream input);
/// <summary>
/// Like MergeFrom(CodedInputStream), but also parses extensions.
......@@ -159,17 +184,14 @@ namespace Google.ProtocolBuffers {
/// Get's the message's type's default instance.
/// <see cref="IMessage{T}.DefaultInstanceForType" />
/// </summary>
IMessage<T> DefaultInstanceForType { get; }
new IMessage<T> DefaultInstanceForType { get; }
/// <summary>
/// Create a builder for messages of the appropriate type for the given field.
/// Messages built with this can then be passed to the various mutation properties
/// and methods.
/// </summary>
/// <typeparam name="TField"></typeparam>
/// <param name="field"></param>
/// <returns></returns>
IBuilder<TField> NewBuilderForField<TField>(Descriptors.FieldDescriptor field) where TField : IMessage<TField>;
new IBuilder<TField> NewBuilderForField<TField>(FieldDescriptor field) where TField : IMessage<TField>;
/// <summary>
/// Clears the field. This is exactly equivalent to calling the generated
......@@ -177,7 +199,7 @@ namespace Google.ProtocolBuffers {
/// </summary>
/// <param name="field"></param>
/// <returns></returns>
IBuilder<T> ClearField(Descriptors.FieldDescriptor field);
new IBuilder<T> ClearField(FieldDescriptor field);
/// <summary>
/// Appends the given value as a new element for the specified repeated field.
......@@ -186,51 +208,45 @@ namespace Google.ProtocolBuffers {
/// the field does not belong to this builder's type, or the value is
/// of the incorrect type
/// </exception>
IBuilder<T> AddRepeatedField(Descriptors.FieldDescriptor field, object value);
/// <summary>
/// <see cref="IMessage{T}.UnknownFields"/>
/// </summary>
UnknownFieldSet UnknownFields { get; set; }
new IBuilder<T> AddRepeatedField(FieldDescriptor field, object value);
/// <summary>
/// Merge some unknown fields into the set for this message.
/// </summary>
IBuilder<T> MergeUnknownFields(UnknownFieldSet unknownFields);
new IBuilder<T> MergeUnknownFields(UnknownFieldSet unknownFields);
#region Convenience methods
// TODO(jonskeet): Implement these as extension methods?
/// <summary>
/// Parse <paramref name="data"/> as a message of this type and merge
/// it with the message being built. This is just a small wrapper around
/// MergeFrom(CodedInputStream).
/// </summary>
IBuilder<T> MergeFrom(ByteString data);
new IBuilder<T> MergeFrom(ByteString data);
/// <summary>
/// Parse <paramref name="data"/> as a message of this type and merge
/// it with the message being built. This is just a small wrapper around
/// MergeFrom(CodedInputStream, ExtensionRegistry).
/// </summary>
IBuilder<T> MergeFrom(ByteString data, ExtensionRegistry extensionRegistry);
new IBuilder<T> MergeFrom(ByteString data, ExtensionRegistry extensionRegistry);
/// <summary>
/// Parse <paramref name="data"/> as a message of this type and merge
/// it with the message being built. This is just a small wrapper around
/// MergeFrom(CodedInputStream).
/// </summary>
IBuilder<T> MergeFrom(byte[] data);
new IBuilder<T> MergeFrom(byte[] data);
/// <summary>
/// Parse <paramref name="data"/> as a message of this type and merge
/// it with the message being built. This is just a small wrapper around
/// MergeFrom(CodedInputStream, ExtensionRegistry).
/// </summary>
IBuilder<T> MergeFrom(byte[] data, ExtensionRegistry extensionRegistry);
new IBuilder<T> MergeFrom(byte[] data, ExtensionRegistry extensionRegistry);
/// <summary>
/// Parse <paramref name="data"/> as a message of this type and merge
/// Parse <paramref name="input"/> as a message of this type and merge
/// it with the message being built. This is just a small wrapper around
/// MergeFrom(CodedInputStream). Note that this method always reads
/// the entire input (unless it throws an exception). If you want it to
......@@ -238,14 +254,14 @@ namespace Google.ProtocolBuffers {
/// stream which limits reading. Despite usually reading the entire
/// stream, this method never closes the stream.
/// </summary>
IBuilder<T> MergeFrom(Stream input);
new IBuilder<T> MergeFrom(Stream input);
/// <summary>
/// Parse <paramref name="data"/> as a message of this type and merge
/// Parse <paramref name="input"/> as a message of this type and merge
/// it with the message being built. This is just a small wrapper around
/// MergeFrom(CodedInputStream, ExtensionRegistry).
/// </summary>
IBuilder<T> MergeFrom(Stream input, ExtensionRegistry extensionRegistry);
new IBuilder<T> MergeFrom(Stream input, ExtensionRegistry extensionRegistry);
#endregion
}
}
......@@ -41,11 +41,11 @@ namespace Google.ProtocolBuffers {
/// field is set iff HasField() returns true for that field. A "repeated"
/// field is set iff GetRepeatedFieldSize() is greater than zero. The
/// values are exactly what would be returned by calling
/// GetField(Descriptors.FieldDescriptor) for each field. The map
/// GetField(FieldDescriptor) for each field. The map
/// is guaranteed to be a sorted map, so iterating over it will return fields
/// in order by field number.
/// </summary>
IDictionary<Descriptors.FieldDescriptor, object> AllFields { get; }
IDictionary<FieldDescriptor, object> AllFields { get; }
/// <summary>
/// Returns true if the given field is set. This is exactly equivalent
......@@ -53,7 +53,7 @@ namespace Google.ProtocolBuffers {
/// </summary>
/// <exception cref="ArgumentException">the field is a repeated field,
/// or it's not a field of this type</exception>
bool HasField(Descriptors.FieldDescriptor field);
bool HasField(FieldDescriptor field);
/// <summary>
/// Obtains the value of the given field, or the default value if
......@@ -61,7 +61,7 @@ namespace Google.ProtocolBuffers {
/// value is returned. For embedded message fields, the sub-message
/// is returned. For repeated fields, an IList&lt;T&gt; is returned.
/// </summary>
object this[Descriptors.FieldDescriptor field] { get; }
object this[FieldDescriptor field] { get; }
/// <summary>
/// Returns the number of elements of a repeated field. This is
......@@ -70,7 +70,7 @@ namespace Google.ProtocolBuffers {
/// </summary>
/// <exception cref="ArgumentException">the field is not a repeated field,
/// or it's not a field of this type</exception>
int GetRepeatedFieldCount(Descriptors.FieldDescriptor field);
int GetRepeatedFieldCount(FieldDescriptor field);
/// <summary>
/// Gets an element of a repeated field. For value type fields
......@@ -81,7 +81,7 @@ namespace Google.ProtocolBuffers {
/// or it's not a field of this type</exception>
/// <exception cref="ArgumentOutOfRangeException">the index is out of
/// range for the repeated field's value</exception>
object this[Descriptors.FieldDescriptor field, int index] { get; }
object this[FieldDescriptor field, int index] { get; }
/// <summary>
/// Returns the unknown fields for this message.
......
......@@ -36,23 +36,34 @@
<Reference Include="System.Xml" />
</ItemGroup>
<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\Lists.cs" />
<Compile Include="Descriptors\EnumValueDescriptor.cs" />
<Compile Include="Descriptors\FieldDescriptor.cs" />
<Compile Include="Descriptors\FieldType.cs" />
<Compile Include="Descriptors\MappedType.cs" />
<Compile Include="Descriptors\MessageDescriptor.cs" />
<Compile Include="ExtensionInfo.cs" />
<Compile Include="ExtensionRegistry.cs" />
<Compile Include="FieldAccess\Delegates.cs" />
<Compile Include="FieldAccess\IFieldAccessor.cs" />
<Compile Include="FieldAccess\FieldAccessorTable.cs" />
<Compile Include="FieldAccess\SingularFieldAccessor.cs" />
<Compile Include="FieldSet.cs" />
<Compile Include="GeneratedExtension.cs" />
<Compile Include="GeneratedMessage.cs" />
<Compile Include="IBuilder.cs" />
<Compile Include="IMessage.cs" />
<Compile Include="InvalidProtocolBufferException.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TextFormat.cs" />
<Compile Include="UninitializedMessageException.cs" />
<Compile Include="UnknownField.cs" />
<Compile Include="UnknownFieldSet.cs" />
<Compile Include="WireFormat.cs" />
</ItemGroup>
......
......@@ -7,5 +7,9 @@ namespace Google.ProtocolBuffers {
public static string PrintToString(IMessage message) {
throw new NotImplementedException();
}
internal static string PrintToString(UnknownFieldSet unknownFieldSet) {
throw new NotImplementedException();
}
}
}
This diff is collapsed.
This diff is collapsed.
......@@ -43,8 +43,8 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// Given a tag value, determines the field number (the upper 29 bits).
/// </summary>
public static uint GetTagFieldNumber(uint tag) {
return tag >> TagTypeBits;
public static int GetTagFieldNumber(uint tag) {
return (int) tag >> TagTypeBits;
}
/// <summary>
......
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