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 { ...@@ -34,13 +34,15 @@ namespace Google.ProtocolBuffers {
#region Unimplemented members of IMessage #region Unimplemented members of IMessage
public abstract MessageDescriptor DescriptorForType { get; } public abstract MessageDescriptor DescriptorForType { get; }
public abstract IDictionary<Descriptors.FieldDescriptor, object> AllFields { get; } public abstract IDictionary<FieldDescriptor, object> AllFields { get; }
public abstract bool HasField(Descriptors.FieldDescriptor field); public abstract bool HasField(FieldDescriptor field);
public abstract object this[Descriptors.FieldDescriptor field] { get; } public abstract object this[FieldDescriptor field] { get; }
public abstract int GetRepeatedFieldCount(Descriptors.FieldDescriptor field); public abstract int GetRepeatedFieldCount(FieldDescriptor field);
public abstract object this[Descriptors.FieldDescriptor field, int index] { get; } public abstract object this[FieldDescriptor field, int index] { get; }
public abstract UnknownFieldSet UnknownFields { get; } public abstract UnknownFieldSet UnknownFields { get; }
public abstract IMessage DefaultInstanceForType { get; } // FIXME
IMessage IMessage.DefaultInstanceForType { get { return null; } }
IBuilder IMessage.CreateBuilderForType() { return null; }
#endregion #endregion
public bool IsInitialized { public bool IsInitialized {
...@@ -152,8 +154,6 @@ namespace Google.ProtocolBuffers { ...@@ -152,8 +154,6 @@ namespace Google.ProtocolBuffers {
codedOutput.Flush(); codedOutput.Flush();
} }
public abstract IBuilder CreateBuilderForType();
public override bool Equals(object other) { public override bool Equals(object other) {
if (other == this) { if (other == this) {
return true; return true;
...@@ -173,5 +173,73 @@ namespace Google.ProtocolBuffers { ...@@ -173,5 +173,73 @@ namespace Google.ProtocolBuffers {
hash = (53 * hash) + AllFields.GetHashCode(); hash = (53 * hash) + AllFields.GetHashCode();
return hash; return hash;
} }
#region IMessage Members
MessageDescriptor IMessage.DescriptorForType {
get { throw new NotImplementedException(); }
}
IDictionary<FieldDescriptor, object> IMessage.AllFields {
get { throw new NotImplementedException(); }
}
bool IMessage.HasField(FieldDescriptor field) {
throw new NotImplementedException();
}
object IMessage.this[FieldDescriptor field] {
get { throw new NotImplementedException(); }
}
int IMessage.GetRepeatedFieldCount(FieldDescriptor field) {
throw new NotImplementedException();
}
object IMessage.this[FieldDescriptor field, int index] {
get { throw new NotImplementedException(); }
}
UnknownFieldSet IMessage.UnknownFields {
get { throw new NotImplementedException(); }
}
bool IMessage.IsInitialized {
get { throw new NotImplementedException(); }
}
void IMessage.WriteTo(CodedOutputStream output) {
throw new NotImplementedException();
}
int IMessage.SerializedSize {
get { throw new NotImplementedException(); }
}
bool IMessage.Equals(object other) {
throw new NotImplementedException();
}
int IMessage.GetHashCode() {
throw new NotImplementedException();
}
string IMessage.ToString() {
throw new NotImplementedException();
}
ByteString IMessage.ToByteString() {
throw new NotImplementedException();
}
byte[] IMessage.ToByteArray() {
throw new NotImplementedException();
}
void IMessage.WriteTo(Stream output) {
throw new NotImplementedException();
}
#endregion
} }
} }
...@@ -105,6 +105,15 @@ namespace Google.ProtocolBuffers { ...@@ -105,6 +105,15 @@ namespace Google.ProtocolBuffers {
return ToString(Encoding.UTF8); 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 // TODO(jonskeet): CopyTo, Equals, GetHashCode if they turn out to be required
/// <summary> /// <summary>
......
...@@ -321,7 +321,7 @@ namespace Google.ProtocolBuffers { ...@@ -321,7 +321,7 @@ namespace Google.ProtocolBuffers {
/// Reads a field of any primitive type. Enums, groups and embedded /// Reads a field of any primitive type. Enums, groups and embedded
/// messages are not handled by this method. /// messages are not handled by this method.
/// </summary> /// </summary>
public object readPrimitiveField(FieldType fieldType) { public object ReadPrimitiveField(FieldType fieldType) {
switch (fieldType) { switch (fieldType) {
case FieldType.Double: return ReadDouble(); case FieldType.Double: return ReadDouble();
case FieldType.Float: return ReadFloat(); case FieldType.Float: return ReadFloat();
......
...@@ -271,7 +271,7 @@ namespace Google.ProtocolBuffers { ...@@ -271,7 +271,7 @@ namespace Google.ProtocolBuffers {
case FieldType.SFixed64: WriteSFixed64(fieldNumber, (long)value); break; case FieldType.SFixed64: WriteSFixed64(fieldNumber, (long)value); break;
case FieldType.SInt32: WriteSInt32(fieldNumber, (int)value); break; case FieldType.SInt32: WriteSInt32(fieldNumber, (int)value); break;
case FieldType.SInt64: WriteSInt64(fieldNumber, (long)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; break;
} }
} }
...@@ -615,7 +615,7 @@ namespace Google.ProtocolBuffers { ...@@ -615,7 +615,7 @@ namespace Google.ProtocolBuffers {
* @param number The field's number. * @param number The field's number.
* @param value Object representing the field's value. Must be of the exact * @param value Object representing the field's value. Must be of the exact
* type which would be returned by * type which would be returned by
* {@link Message#getField(Descriptors.FieldDescriptor)} for * {@link Message#getField(FieldDescriptor)} for
* this field. * this field.
*/ */
public static int ComputeFieldSize(FieldType fieldType, int fieldNumber, Object value) { public static int ComputeFieldSize(FieldType fieldType, int fieldNumber, Object value) {
...@@ -637,7 +637,7 @@ namespace Google.ProtocolBuffers { ...@@ -637,7 +637,7 @@ namespace Google.ProtocolBuffers {
case FieldType.SFixed64: return ComputeSFixed64Size(fieldNumber, (long)value); case FieldType.SFixed64: return ComputeSFixed64Size(fieldNumber, (long)value);
case FieldType.SInt32: return ComputeSInt32Size(fieldNumber, (int)value); case FieldType.SInt32: return ComputeSInt32Size(fieldNumber, (int)value);
case FieldType.SInt64: return ComputeSInt64Size(fieldNumber, (long)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: default:
throw new ArgumentOutOfRangeException("Invalid field type " + fieldType); 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 { ...@@ -13,5 +13,17 @@ namespace Google.ProtocolBuffers.Descriptors {
public FieldType FieldType { get; set; } public FieldType FieldType { get; set; }
public int FieldNumber { 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 { ...@@ -7,6 +7,14 @@ namespace Google.ProtocolBuffers.Descriptors {
/// Type as it's mapped onto a .NET type. /// Type as it's mapped onto a .NET type.
/// </summary> /// </summary>
public enum MappedType { public enum MappedType {
Message Int32,
Int64,
Single,
Double,
Boolean,
String,
ByteString,
Message,
Enum
} }
} }
...@@ -5,5 +5,6 @@ namespace Google.ProtocolBuffers.Descriptors { ...@@ -5,5 +5,6 @@ namespace Google.ProtocolBuffers.Descriptors {
public class MessageDescriptor { public class MessageDescriptor {
public IList<FieldDescriptor> Fields; public IList<FieldDescriptor> Fields;
public DescriptorProtos.MessageOptions Options; 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 @@ ...@@ -13,7 +13,167 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
using System.Collections.Generic;
using Google.ProtocolBuffers.Descriptors;
using System;
namespace Google.ProtocolBuffers { 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 { ...@@ -29,7 +29,6 @@ namespace Google.ProtocolBuffers {
/// how IEnumerable and IEnumerable&lt;T&gt; work. /// how IEnumerable and IEnumerable&lt;T&gt; work.
/// </summary> /// </summary>
public interface IBuilder { public interface IBuilder {
IBuilder MergeFrom(CodedInputStream codedInputStream, ExtensionRegistry extensionRegistry);
/// <summary> /// <summary>
/// Returns true iff all required fields in the message and all /// Returns true iff all required fields in the message and all
/// embedded messages are set. /// embedded messages are set.
...@@ -41,15 +40,15 @@ namespace Google.ProtocolBuffers { ...@@ -41,15 +40,15 @@ namespace Google.ProtocolBuffers {
/// The returned map may or may not reflect future changes to the builder. /// The returned map may or may not reflect future changes to the builder.
/// Either way, the returned map is unmodifiable. /// Either way, the returned map is unmodifiable.
/// </summary> /// </summary>
IDictionary<ProtocolBuffers.Descriptors.FieldDescriptor, object> AllFields { get; } IDictionary<FieldDescriptor, object> AllFields { get; }
/// <summary> /// <summary>
/// Allows getting and setting of a field. /// Allows getting and setting of a field.
/// <see cref="IMessage{T}.Item(Descriptors.FieldDescriptor)"/> /// <see cref="IMessage{T}.Item(FieldDescriptor)"/>
/// </summary> /// </summary>
/// <param name="field"></param> /// <param name="field"></param>
/// <returns></returns> /// <returns></returns>
object this[Descriptors.FieldDescriptor field] { get; set; } object this[FieldDescriptor field] { get; set; }
/// <summary> /// <summary>
/// Get the message's type's descriptor. /// Get the message's type's descriptor.
...@@ -62,18 +61,44 @@ namespace Google.ProtocolBuffers { ...@@ -62,18 +61,44 @@ namespace Google.ProtocolBuffers {
/// </summary> /// </summary>
/// <param name="field"></param> /// <param name="field"></param>
/// <returns></returns> /// <returns></returns>
int GetRepeatedFieldCount(Descriptors.FieldDescriptor field); int GetRepeatedFieldCount(FieldDescriptor field);
/// <summary> /// <summary>
/// Allows getting and setting of a repeated field value. /// 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> /// </summary>
object this[Descriptors.FieldDescriptor field, int index] { get; set; } object this[FieldDescriptor field, int index] { get; set; }
/// <summary> /// <summary>
/// <see cref="IMessage{T}.HasField"/> /// <see cref="IMessage{T}.HasField"/>
/// </summary> /// </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> /// <summary>
...@@ -85,7 +110,7 @@ namespace Google.ProtocolBuffers { ...@@ -85,7 +110,7 @@ namespace Google.ProtocolBuffers {
/// <summary> /// <summary>
/// Resets all fields to their default values. /// Resets all fields to their default values.
/// </summary> /// </summary>
IBuilder<T> Clear(); new IBuilder<T> Clear();
/// <summary> /// <summary>
/// Merge the specified other message into the message being /// Merge the specified other message into the message being
...@@ -111,20 +136,20 @@ namespace Google.ProtocolBuffers { ...@@ -111,20 +136,20 @@ namespace Google.ProtocolBuffers {
/// <exception cref="UninitializedMessageException">the message /// <exception cref="UninitializedMessageException">the message
/// is missing one or more required fields; use BuildPartial to bypass /// is missing one or more required fields; use BuildPartial to bypass
/// this check</exception> /// this check</exception>
IMessage<T> Build(); new IMessage<T> Build();
/// <summary> /// <summary>
/// Like Build(), but does not throw an exception if the message is missing /// Like Build(), but does not throw an exception if the message is missing
/// required fields. Instead, a partial message is returned. /// required fields. Instead, a partial message is returned.
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
IMessage<T> BuildPartial(); new IMessage<T> BuildPartial();
/// <summary> /// <summary>
/// Clones this builder. /// Clones this builder.
/// TODO(jonskeet): Explain depth of clone. /// TODO(jonskeet): Explain depth of clone.
/// </summary> /// </summary>
IBuilder<T> Clone(); new IBuilder<T> Clone();
/// <summary> /// <summary>
/// Parses a message of this type from the input and merges it with this /// Parses a message of this type from the input and merges it with this
...@@ -145,7 +170,7 @@ namespace Google.ProtocolBuffers { ...@@ -145,7 +170,7 @@ namespace Google.ProtocolBuffers {
/// Use BuildPartial to build, which ignores missing required fields. /// Use BuildPartial to build, which ignores missing required fields.
/// </list> /// </list>
/// </remarks> /// </remarks>
IBuilder<T> MergeFrom(CodedInputStream input); new IBuilder<T> MergeFrom(CodedInputStream input);
/// <summary> /// <summary>
/// Like MergeFrom(CodedInputStream), but also parses extensions. /// Like MergeFrom(CodedInputStream), but also parses extensions.
...@@ -159,17 +184,14 @@ namespace Google.ProtocolBuffers { ...@@ -159,17 +184,14 @@ namespace Google.ProtocolBuffers {
/// Get's the message's type's default instance. /// Get's the message's type's default instance.
/// <see cref="IMessage{T}.DefaultInstanceForType" /> /// <see cref="IMessage{T}.DefaultInstanceForType" />
/// </summary> /// </summary>
IMessage<T> DefaultInstanceForType { get; } new IMessage<T> DefaultInstanceForType { get; }
/// <summary> /// <summary>
/// Create a builder for messages of the appropriate type for the given field. /// 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 /// Messages built with this can then be passed to the various mutation properties
/// and methods. /// and methods.
/// </summary> /// </summary>
/// <typeparam name="TField"></typeparam> new IBuilder<TField> NewBuilderForField<TField>(FieldDescriptor field) where TField : IMessage<TField>;
/// <param name="field"></param>
/// <returns></returns>
IBuilder<TField> NewBuilderForField<TField>(Descriptors.FieldDescriptor field) where TField : IMessage<TField>;
/// <summary> /// <summary>
/// Clears the field. This is exactly equivalent to calling the generated /// Clears the field. This is exactly equivalent to calling the generated
...@@ -177,7 +199,7 @@ namespace Google.ProtocolBuffers { ...@@ -177,7 +199,7 @@ namespace Google.ProtocolBuffers {
/// </summary> /// </summary>
/// <param name="field"></param> /// <param name="field"></param>
/// <returns></returns> /// <returns></returns>
IBuilder<T> ClearField(Descriptors.FieldDescriptor field); new IBuilder<T> ClearField(FieldDescriptor field);
/// <summary> /// <summary>
/// Appends the given value as a new element for the specified repeated field. /// Appends the given value as a new element for the specified repeated field.
...@@ -186,51 +208,45 @@ namespace Google.ProtocolBuffers { ...@@ -186,51 +208,45 @@ namespace Google.ProtocolBuffers {
/// the field does not belong to this builder's type, or the value is /// the field does not belong to this builder's type, or the value is
/// of the incorrect type /// of the incorrect type
/// </exception> /// </exception>
IBuilder<T> AddRepeatedField(Descriptors.FieldDescriptor field, object value); new IBuilder<T> AddRepeatedField(FieldDescriptor field, object value);
/// <summary>
/// <see cref="IMessage{T}.UnknownFields"/>
/// </summary>
UnknownFieldSet UnknownFields { get; set; }
/// <summary> /// <summary>
/// Merge some unknown fields into the set for this message. /// Merge some unknown fields into the set for this message.
/// </summary> /// </summary>
IBuilder<T> MergeUnknownFields(UnknownFieldSet unknownFields); new IBuilder<T> MergeUnknownFields(UnknownFieldSet unknownFields);
#region Convenience methods #region Convenience methods
// TODO(jonskeet): Implement these as extension methods? // TODO(jonskeet): Implement these as extension methods?
/// <summary> /// <summary>
/// Parse <paramref name="data"/> as a message of this type and merge /// 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 /// it with the message being built. This is just a small wrapper around
/// MergeFrom(CodedInputStream). /// MergeFrom(CodedInputStream).
/// </summary> /// </summary>
IBuilder<T> MergeFrom(ByteString data); new IBuilder<T> MergeFrom(ByteString data);
/// <summary> /// <summary>
/// Parse <paramref name="data"/> as a message of this type and merge /// 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 /// it with the message being built. This is just a small wrapper around
/// MergeFrom(CodedInputStream, ExtensionRegistry). /// MergeFrom(CodedInputStream, ExtensionRegistry).
/// </summary> /// </summary>
IBuilder<T> MergeFrom(ByteString data, ExtensionRegistry extensionRegistry); new IBuilder<T> MergeFrom(ByteString data, ExtensionRegistry extensionRegistry);
/// <summary> /// <summary>
/// Parse <paramref name="data"/> as a message of this type and merge /// 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 /// it with the message being built. This is just a small wrapper around
/// MergeFrom(CodedInputStream). /// MergeFrom(CodedInputStream).
/// </summary> /// </summary>
IBuilder<T> MergeFrom(byte[] data); new IBuilder<T> MergeFrom(byte[] data);
/// <summary> /// <summary>
/// Parse <paramref name="data"/> as a message of this type and merge /// 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 /// it with the message being built. This is just a small wrapper around
/// MergeFrom(CodedInputStream, ExtensionRegistry). /// MergeFrom(CodedInputStream, ExtensionRegistry).
/// </summary> /// </summary>
IBuilder<T> MergeFrom(byte[] data, ExtensionRegistry extensionRegistry); new IBuilder<T> MergeFrom(byte[] data, ExtensionRegistry extensionRegistry);
/// <summary> /// <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 /// it with the message being built. This is just a small wrapper around
/// MergeFrom(CodedInputStream). Note that this method always reads /// MergeFrom(CodedInputStream). Note that this method always reads
/// the entire input (unless it throws an exception). If you want it to /// the entire input (unless it throws an exception). If you want it to
...@@ -238,14 +254,14 @@ namespace Google.ProtocolBuffers { ...@@ -238,14 +254,14 @@ namespace Google.ProtocolBuffers {
/// stream which limits reading. Despite usually reading the entire /// stream which limits reading. Despite usually reading the entire
/// stream, this method never closes the stream. /// stream, this method never closes the stream.
/// </summary> /// </summary>
IBuilder<T> MergeFrom(Stream input); new IBuilder<T> MergeFrom(Stream input);
/// <summary> /// <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 /// it with the message being built. This is just a small wrapper around
/// MergeFrom(CodedInputStream, ExtensionRegistry). /// MergeFrom(CodedInputStream, ExtensionRegistry).
/// </summary> /// </summary>
IBuilder<T> MergeFrom(Stream input, ExtensionRegistry extensionRegistry); new IBuilder<T> MergeFrom(Stream input, ExtensionRegistry extensionRegistry);
#endregion #endregion
} }
} }
...@@ -41,11 +41,11 @@ namespace Google.ProtocolBuffers { ...@@ -41,11 +41,11 @@ namespace Google.ProtocolBuffers {
/// field is set iff HasField() returns true for that field. A "repeated" /// field is set iff HasField() returns true for that field. A "repeated"
/// field is set iff GetRepeatedFieldSize() is greater than zero. The /// field is set iff GetRepeatedFieldSize() is greater than zero. The
/// values are exactly what would be returned by calling /// 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 /// is guaranteed to be a sorted map, so iterating over it will return fields
/// in order by field number. /// in order by field number.
/// </summary> /// </summary>
IDictionary<Descriptors.FieldDescriptor, object> AllFields { get; } IDictionary<FieldDescriptor, object> AllFields { get; }
/// <summary> /// <summary>
/// Returns true if the given field is set. This is exactly equivalent /// Returns true if the given field is set. This is exactly equivalent
...@@ -53,7 +53,7 @@ namespace Google.ProtocolBuffers { ...@@ -53,7 +53,7 @@ namespace Google.ProtocolBuffers {
/// </summary> /// </summary>
/// <exception cref="ArgumentException">the field is a repeated field, /// <exception cref="ArgumentException">the field is a repeated field,
/// or it's not a field of this type</exception> /// or it's not a field of this type</exception>
bool HasField(Descriptors.FieldDescriptor field); bool HasField(FieldDescriptor field);
/// <summary> /// <summary>
/// Obtains the value of the given field, or the default value if /// Obtains the value of the given field, or the default value if
...@@ -61,7 +61,7 @@ namespace Google.ProtocolBuffers { ...@@ -61,7 +61,7 @@ namespace Google.ProtocolBuffers {
/// value is returned. For embedded message fields, the sub-message /// value is returned. For embedded message fields, the sub-message
/// is returned. For repeated fields, an IList&lt;T&gt; is returned. /// is returned. For repeated fields, an IList&lt;T&gt; is returned.
/// </summary> /// </summary>
object this[Descriptors.FieldDescriptor field] { get; } object this[FieldDescriptor field] { get; }
/// <summary> /// <summary>
/// Returns the number of elements of a repeated field. This is /// Returns the number of elements of a repeated field. This is
...@@ -70,7 +70,7 @@ namespace Google.ProtocolBuffers { ...@@ -70,7 +70,7 @@ namespace Google.ProtocolBuffers {
/// </summary> /// </summary>
/// <exception cref="ArgumentException">the field is not a repeated field, /// <exception cref="ArgumentException">the field is not a repeated field,
/// or it's not a field of this type</exception> /// or it's not a field of this type</exception>
int GetRepeatedFieldCount(Descriptors.FieldDescriptor field); int GetRepeatedFieldCount(FieldDescriptor field);
/// <summary> /// <summary>
/// Gets an element of a repeated field. For value type fields /// Gets an element of a repeated field. For value type fields
...@@ -81,7 +81,7 @@ namespace Google.ProtocolBuffers { ...@@ -81,7 +81,7 @@ namespace Google.ProtocolBuffers {
/// or it's not a field of this type</exception> /// or it's not a field of this type</exception>
/// <exception cref="ArgumentOutOfRangeException">the index is out of /// <exception cref="ArgumentOutOfRangeException">the index is out of
/// range for the repeated field's value</exception> /// range for the repeated field's value</exception>
object this[Descriptors.FieldDescriptor field, int index] { get; } object this[FieldDescriptor field, int index] { get; }
/// <summary> /// <summary>
/// Returns the unknown fields for this message. /// Returns the unknown fields for this message.
......
...@@ -36,23 +36,34 @@ ...@@ -36,23 +36,34 @@
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="AbstractBuilder.cs" />
<Compile Include="AbstractMessage.cs" /> <Compile Include="AbstractMessage.cs" />
<Compile Include="Autogenerated.cs" /> <Compile Include="Autogenerated.cs" />
<Compile Include="ByteString.cs" /> <Compile Include="ByteString.cs" />
<Compile Include="CodedInputStream.cs" /> <Compile Include="CodedInputStream.cs" />
<Compile Include="CodedOutputStream.cs" /> <Compile Include="CodedOutputStream.cs" />
<Compile Include="Collections\Lists.cs" />
<Compile Include="Descriptors\EnumValueDescriptor.cs" /> <Compile Include="Descriptors\EnumValueDescriptor.cs" />
<Compile Include="Descriptors\FieldDescriptor.cs" /> <Compile Include="Descriptors\FieldDescriptor.cs" />
<Compile Include="Descriptors\FieldType.cs" /> <Compile Include="Descriptors\FieldType.cs" />
<Compile Include="Descriptors\MappedType.cs" /> <Compile Include="Descriptors\MappedType.cs" />
<Compile Include="Descriptors\MessageDescriptor.cs" /> <Compile Include="Descriptors\MessageDescriptor.cs" />
<Compile Include="ExtensionInfo.cs" />
<Compile Include="ExtensionRegistry.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="IBuilder.cs" />
<Compile Include="IMessage.cs" /> <Compile Include="IMessage.cs" />
<Compile Include="InvalidProtocolBufferException.cs" /> <Compile Include="InvalidProtocolBufferException.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TextFormat.cs" /> <Compile Include="TextFormat.cs" />
<Compile Include="UninitializedMessageException.cs" /> <Compile Include="UninitializedMessageException.cs" />
<Compile Include="UnknownField.cs" />
<Compile Include="UnknownFieldSet.cs" /> <Compile Include="UnknownFieldSet.cs" />
<Compile Include="WireFormat.cs" /> <Compile Include="WireFormat.cs" />
</ItemGroup> </ItemGroup>
......
...@@ -7,5 +7,9 @@ namespace Google.ProtocolBuffers { ...@@ -7,5 +7,9 @@ namespace Google.ProtocolBuffers {
public static string PrintToString(IMessage message) { public static string PrintToString(IMessage message) {
throw new NotImplementedException(); 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 { ...@@ -43,8 +43,8 @@ namespace Google.ProtocolBuffers {
/// <summary> /// <summary>
/// Given a tag value, determines the field number (the upper 29 bits). /// Given a tag value, determines the field number (the upper 29 bits).
/// </summary> /// </summary>
public static uint GetTagFieldNumber(uint tag) { public static int GetTagFieldNumber(uint tag) {
return tag >> TagTypeBits; return (int) tag >> TagTypeBits;
} }
/// <summary> /// <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