Commit 80e73b92 authored by csharptest's avatar csharptest

Completed abstract lite builder and message

parent 97f86ce9
This diff is collapsed.
......@@ -42,7 +42,7 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// Implementation of the non-generic IMessage interface as far as possible.
/// </summary>
public abstract class AbstractMessage<TMessage, TBuilder> : IMessage<TMessage, TBuilder>
public abstract class AbstractMessage<TMessage, TBuilder> : AbstractMessageLite<TMessage, TBuilder>, IMessage<TMessage, TBuilder>
where TMessage : AbstractMessage<TMessage, TBuilder>
where TBuilder : AbstractBuilder<TMessage, TBuilder> {
/// <summary>
......@@ -59,28 +59,13 @@ namespace Google.ProtocolBuffers {
public abstract int GetRepeatedFieldCount(FieldDescriptor field);
public abstract object this[FieldDescriptor field, int index] { get; }
public abstract UnknownFieldSet UnknownFields { get; }
public abstract TMessage DefaultInstanceForType { get; }
public abstract TBuilder CreateBuilderForType();
public abstract TBuilder ToBuilder();
#endregion
public IBuilder WeakCreateBuilderForType() {
return CreateBuilderForType();
}
public IBuilder WeakToBuilder() {
return ToBuilder();
}
IMessageLite IMessageLite.WeakDefaultInstanceForType {
get { return DefaultInstanceForType; }
}
public IMessage WeakDefaultInstanceForType {
get { return DefaultInstanceForType; }
}
public virtual bool IsInitialized {
/// <summary>
/// Returns true iff all required fields in the message and all embedded
/// messages are set.
/// </summary>
public override bool IsInitialized {
get {
// Check that all required fields are present.
foreach (FieldDescriptor field in DescriptorForType.Fields) {
......@@ -116,7 +101,19 @@ namespace Google.ProtocolBuffers {
return TextFormat.PrintToString(this);
}
public virtual void WriteTo(CodedOutputStream output) {
/// <summary>
/// Serializes the message and writes it to the given output stream.
/// This does not flush or close the stream.
/// </summary>
/// <remarks>
/// Protocol Buffers are not self-delimiting. Therefore, if you write
/// any more data to the stream after the message, you must somehow ensure
/// that the parser on the receiving end does not interpret this as being
/// part of the protocol message. One way of doing this is by writing the size
/// of the message before the data, then making sure you limit the input to
/// that size when receiving the data. Alternatively, use WriteDelimitedTo(Stream).
/// </remarks>
public override void WriteTo(CodedOutputStream output) {
foreach (KeyValuePair<FieldDescriptor, object> entry in AllFields) {
FieldDescriptor field = entry.Key;
if (field.IsRepeated) {
......@@ -151,7 +148,11 @@ namespace Google.ProtocolBuffers {
}
}
public virtual int SerializedSize {
/// <summary>
/// Returns the number of bytes required to encode this message.
/// The result is only computed on the first call and memoized after that.
/// </summary>
public override int SerializedSize {
get {
if (memoizedSize != null) {
return memoizedSize.Value;
......@@ -192,33 +193,12 @@ namespace Google.ProtocolBuffers {
}
}
public ByteString ToByteString() {
ByteString.CodedBuilder output = new ByteString.CodedBuilder(SerializedSize);
WriteTo(output.CodedOutput);
return output.Build();
}
public byte[] ToByteArray() {
byte[] result = new byte[SerializedSize];
CodedOutputStream output = CodedOutputStream.CreateInstance(result);
WriteTo(output);
output.CheckNoSpaceLeft();
return result;
}
public void WriteTo(Stream output) {
CodedOutputStream codedOutput = CodedOutputStream.CreateInstance(output);
WriteTo(codedOutput);
codedOutput.Flush();
}
public void WriteDelimitedTo(Stream output) {
CodedOutputStream codedOutput = CodedOutputStream.CreateInstance(output);
codedOutput.WriteRawVarint32((uint) SerializedSize);
WriteTo(codedOutput);
codedOutput.Flush();
}
/// <summary>
/// Compares the specified object with this message for equality.
/// Returns true iff the given object is a message of the same type
/// (as defined by DescriptorForType) and has identical values
/// for all its fields.
/// </summary>
public override bool Equals(object other) {
if (other == this) {
return true;
......@@ -230,6 +210,10 @@ namespace Google.ProtocolBuffers {
return Dictionaries.Equals(AllFields, otherMessage.AllFields) && UnknownFields.Equals(otherMessage.UnknownFields);
}
/// <summary>
/// Returns the hash code value for this message.
/// TODO(jonskeet): Specify the hash algorithm, but better than the Java one!
/// </summary>
public override int GetHashCode() {
int hash = 41;
hash = (19 * hash) + DescriptorForType.GetHashCode();
......@@ -238,11 +222,20 @@ namespace Google.ProtocolBuffers {
return hash;
}
IBuilderLite IMessageLite.WeakCreateBuilderForType() {
return WeakCreateBuilderForType(); }
#region Explicit Members
IBuilder IMessage.WeakCreateBuilderForType() {
return CreateBuilderForType();
}
IBuilderLite IMessageLite.WeakToBuilder() {
return WeakToBuilder();
IBuilder IMessage.WeakToBuilder() {
return ToBuilder();
}
IMessage IMessage.WeakDefaultInstanceForType {
get { return DefaultInstanceForType; }
}
#endregion
}
}
......@@ -261,7 +261,7 @@ namespace Google.ProtocolBuffers {
/// Reads a group field value from the stream.
/// </summary>
public void ReadGroup(int fieldNumber, IBuilderLite builder,
ExtensionRegistryLite extensionRegistry) {
ExtensionRegistry extensionRegistry) {
if (recursionDepth >= recursionLimit) {
throw InvalidProtocolBufferException.RecursionLimitExceeded();
}
......@@ -290,7 +290,7 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// Reads an embedded message field value from the stream.
/// </summary>
public void ReadMessage(IBuilderLite builder, ExtensionRegistryLite extensionRegistry) {
public void ReadMessage(IBuilderLite builder, ExtensionRegistry extensionRegistry) {
int length = (int) ReadRawVarint32();
if (recursionDepth >= recursionLimit) {
throw InvalidProtocolBufferException.RecursionLimitExceeded();
......
......@@ -88,8 +88,8 @@ namespace Google.ProtocolBuffers {
/// could take advantage of this to inject a mutable object into a message
/// belonging to privileged code and create mischief.</para>
/// </remarks>
public sealed class ExtensionRegistry : ExtensionRegistryLite {
public sealed partial class ExtensionRegistry {
#if !LITE
private static readonly ExtensionRegistry empty = new ExtensionRegistry(
new Dictionary<string, ExtensionInfo>(),
new Dictionary<ExtensionIntPair, IGeneratedExtensionLite>(),
......@@ -100,7 +100,7 @@ namespace Google.ProtocolBuffers {
private ExtensionRegistry(IDictionary<String, ExtensionInfo> extensionsByName,
IDictionary<ExtensionIntPair, IGeneratedExtensionLite> extensionsByNumber,
bool readOnly)
: base(extensionsByNumber, readOnly) {
: this(extensionsByNumber, readOnly) {
this.extensionsByName = extensionsByName;
}
......@@ -112,19 +112,10 @@ namespace Google.ProtocolBuffers {
new Dictionary<ExtensionIntPair, IGeneratedExtensionLite>(), false);
}
/// <summary>
/// Get the unmodifiable singleton empty instance.
/// </summary>
public static ExtensionRegistry Empty {
get { return empty; }
}
public new ExtensionRegistry AsReadOnly() {
public ExtensionRegistry AsReadOnly() {
return new ExtensionRegistry(extensionsByName, extensionsByNumber, true);
}
protected override ExtensionRegistryLite MakeReadOnly() {
return AsReadOnly();
}
#endif
/// <summary>
/// Finds an extension by fully-qualified field name, in the
......
......@@ -37,11 +37,10 @@ using System;
namespace Google.ProtocolBuffers {
/// <summary>
/// A table of known extensions, searchable by name or field number. When
/// parsing a protocol message that might have extensions, you must provide
/// an <see cref="ExtensionRegistryLite"/> in which you have registered any extensions
/// an <see cref="ExtensionRegistry"/> in which you have registered any extensions
/// that you want to be able to parse. Otherwise, those extensions will just
/// be treated like unknown fields.
/// </summary>
......@@ -62,7 +61,7 @@ namespace Google.ProtocolBuffers {
/// Then you might write code like:
///
/// <code>
/// ExtensionRegistryLite registry = ExtensionRegistryLite.CreateInstance();
/// extensionRegistry registry = extensionRegistry.CreateInstance();
/// registry.Add(MyProto.Bar);
/// MyProto.Foo message = MyProto.Foo.ParseFrom(input, registry);
/// </code>
......@@ -89,43 +88,40 @@ namespace Google.ProtocolBuffers {
/// could take advantage of this to inject a mutable object into a message
/// belonging to privileged code and create mischief.</para>
/// </remarks>
public class ExtensionRegistryLite {
private static readonly ExtensionRegistryLite empty = new ExtensionRegistryLite(
new Dictionary<ExtensionIntPair, IGeneratedExtensionLite>(),
true);
public sealed partial class ExtensionRegistry {
private readonly IDictionary<ExtensionIntPair, IGeneratedExtensionLite> extensionsByNumber;
private readonly bool readOnly;
protected readonly IDictionary<ExtensionIntPair, IGeneratedExtensionLite> extensionsByNumber;
protected readonly bool readOnly;
protected ExtensionRegistryLite(IDictionary<ExtensionIntPair, IGeneratedExtensionLite> extensionsByNumber,
private ExtensionRegistry(IDictionary<ExtensionIntPair, IGeneratedExtensionLite> extensionsByNumber,
bool readOnly) {
this.extensionsByNumber = extensionsByNumber;
this.readOnly = readOnly;
}
#if LITE
private static readonly ExtensionRegistry empty = new ExtensionRegistry(
new Dictionary<ExtensionIntPair, IGeneratedExtensionLite>(),
true);
/// <summary>
/// Construct a new, empty instance.
/// </summary>
public static ExtensionRegistryLite CreateInstance() {
return new ExtensionRegistryLite(
public static ExtensionRegistry CreateInstance() {
return new ExtensionRegistry(
new Dictionary<ExtensionIntPair, IGeneratedExtensionLite>(), false);
}
public ExtensionRegistry AsReadOnly() {
return new ExtensionRegistry(extensionsByNumber, true);
}
#endif
/// <summary>
/// Get the unmodifiable singleton empty instance.
/// </summary>
public static ExtensionRegistryLite Empty {
public static ExtensionRegistry Empty {
get { return empty; }
}
#endif
public ExtensionRegistryLite AsReadOnly() {
return MakeReadOnly();
}
protected virtual ExtensionRegistryLite MakeReadOnly() {
return new ExtensionRegistryLite(extensionsByNumber, true);
}
/// <summary>
/// Finds an extension by containing type and field number.
......@@ -142,7 +138,7 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// Add an extension from a generated file to the registry.
/// </summary>
public virtual void Add(IGeneratedExtensionLite extension) {
public void Add(IGeneratedExtensionLite extension) {
if (readOnly) {
throw new InvalidOperationException("Cannot add entries to a read-only extension registry");
}
......@@ -155,7 +151,7 @@ namespace Google.ProtocolBuffers {
/// Nested type just used to represent a pair of MessageDescriptor and int, as
/// the key into the "by number" map.
/// </summary>
protected struct ExtensionIntPair : IEquatable<ExtensionIntPair> {
private struct ExtensionIntPair : IEquatable<ExtensionIntPair> {
readonly object msgType;
readonly int number;
......
......@@ -123,9 +123,9 @@ namespace Google.ProtocolBuffers {
IBuilder WeakClearField(FieldDescriptor field);
IBuilder WeakMergeFrom(IMessage message);
new IBuilder WeakMergeFrom(ByteString data);
new IBuilder WeakMergeFrom(ByteString data, ExtensionRegistryLite registry);
new IBuilder WeakMergeFrom(ByteString data, ExtensionRegistry registry);
new IBuilder WeakMergeFrom(CodedInputStream input);
new IBuilder WeakMergeFrom(CodedInputStream input, ExtensionRegistryLite registry);
new IBuilder WeakMergeFrom(CodedInputStream input, ExtensionRegistry registry);
new IMessage WeakBuild();
new IMessage WeakBuildPartial();
new IBuilder WeakClone();
......@@ -150,21 +150,6 @@ namespace Google.ProtocolBuffers {
/// </summary>
new TBuilder Clear();
/// <summary>
/// Merge the specified other message into the message being
/// built. Merging occurs as follows. For each field:
/// For singular primitive fields, if the field is set in <paramref name="other"/>,
/// then <paramref name="other"/>'s value overwrites the value in this message.
/// For singular message fields, if the field is set in <paramref name="other"/>,
/// it is merged into the corresponding sub-message of this message using the same
/// merging rules.
/// For repeated fields, the elements in <paramref name="other"/> are concatenated
/// with the elements in this message.
/// </summary>
/// <param name="other"></param>
/// <returns></returns>
new TBuilder MergeFrom(TMessage other);
/// <summary>
/// Merge the specified other message which may be a different implementation of
/// the same message descriptor.
......@@ -221,7 +206,7 @@ namespace Google.ProtocolBuffers {
/// in <paramref name="extensionRegistry"/>. Extensions not in the registry
/// will be treated as unknown fields.
/// </summary>
new TBuilder MergeFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry);
new TBuilder MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry);
/// <summary>
/// Get's the message's type's default instance.
......@@ -263,7 +248,7 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// Like MergeDelimitedFrom(Stream) but supporting extensions.
/// </summary>
new TBuilder MergeDelimitedFrom(Stream input, ExtensionRegistryLite extensionRegistry);
new TBuilder MergeDelimitedFrom(Stream input, ExtensionRegistry extensionRegistry);
#region Convenience methods
/// <summary>
......@@ -276,9 +261,9 @@ namespace Google.ProtocolBuffers {
/// <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, ExtensionRegistryLite).
/// MergeFrom(CodedInputStream, extensionRegistry).
/// </summary>
new TBuilder MergeFrom(ByteString data, ExtensionRegistryLite extensionRegistry);
new TBuilder MergeFrom(ByteString data, ExtensionRegistry extensionRegistry);
/// <summary>
/// Parse <paramref name="data"/> as a message of this type and merge
......@@ -290,9 +275,9 @@ namespace Google.ProtocolBuffers {
/// <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, ExtensionRegistryLite).
/// MergeFrom(CodedInputStream, extensionRegistry).
/// </summary>
new TBuilder MergeFrom(byte[] data, ExtensionRegistryLite extensionRegistry);
new TBuilder MergeFrom(byte[] data, ExtensionRegistry extensionRegistry);
/// <summary>
/// Parse <paramref name="input"/> as a message of this type and merge
......@@ -309,9 +294,9 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// 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, ExtensionRegistryLite).
/// MergeFrom(CodedInputStream, extensionRegistry).
/// </summary>
new TBuilder MergeFrom(Stream input, ExtensionRegistryLite extensionRegistry);
new TBuilder MergeFrom(Stream input, ExtensionRegistry extensionRegistry);
#endregion
}
}
......@@ -56,9 +56,9 @@ namespace Google.ProtocolBuffers {
IBuilderLite WeakClear();
IBuilderLite WeakMergeFrom(IMessageLite message);
IBuilderLite WeakMergeFrom(ByteString data);
IBuilderLite WeakMergeFrom(ByteString data, ExtensionRegistryLite registry);
IBuilderLite WeakMergeFrom(ByteString data, ExtensionRegistry registry);
IBuilderLite WeakMergeFrom(CodedInputStream input);
IBuilderLite WeakMergeFrom(CodedInputStream input, ExtensionRegistryLite registry);
IBuilderLite WeakMergeFrom(CodedInputStream input, ExtensionRegistry registry);
IMessageLite WeakBuild();
IMessageLite WeakBuildPartial();
IBuilderLite WeakClone();
......@@ -80,21 +80,6 @@ namespace Google.ProtocolBuffers {
/// </summary>
TBuilder Clear();
/// <summary>
/// Merge the specified other message into the message being
/// built. Merging occurs as follows. For each field:
/// For singular primitive fields, if the field is set in <paramref name="other"/>,
/// then <paramref name="other"/>'s value overwrites the value in this message.
/// For singular message fields, if the field is set in <paramref name="other"/>,
/// it is merged into the corresponding sub-message of this message using the same
/// merging rules.
/// For repeated fields, the elements in <paramref name="other"/> are concatenated
/// with the elements in this message.
/// </summary>
/// <param name="other"></param>
/// <returns></returns>
TBuilder MergeFrom(TMessage other);
/// <summary>
/// Merge the specified other message which may be a different implementation of
/// the same message descriptor.
......@@ -151,7 +136,7 @@ namespace Google.ProtocolBuffers {
/// in <paramref name="extensionRegistry"/>. Extensions not in the registry
/// will be treated as unknown fields.
/// </summary>
TBuilder MergeFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry);
TBuilder MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry);
/// <summary>
/// Get's the message's type's default instance.
......@@ -171,7 +156,7 @@ namespace Google.ProtocolBuffers {
/// <summary>
/// Like MergeDelimitedFrom(Stream) but supporting extensions.
/// </summary>
TBuilder MergeDelimitedFrom(Stream input, ExtensionRegistryLite extensionRegistry);
TBuilder MergeDelimitedFrom(Stream input, ExtensionRegistry extensionRegistry);
#region Convenience methods
/// <summary>
......@@ -186,7 +171,7 @@ namespace Google.ProtocolBuffers {
/// it with the message being built. This is just a small wrapper around
/// MergeFrom(CodedInputStream, ExtensionRegistry).
/// </summary>
TBuilder MergeFrom(ByteString data, ExtensionRegistryLite extensionRegistry);
TBuilder MergeFrom(ByteString data, ExtensionRegistry extensionRegistry);
/// <summary>
/// Parse <paramref name="data"/> as a message of this type and merge
......@@ -200,7 +185,7 @@ namespace Google.ProtocolBuffers {
/// it with the message being built. This is just a small wrapper around
/// MergeFrom(CodedInputStream, ExtensionRegistry).
/// </summary>
TBuilder MergeFrom(byte[] data, ExtensionRegistryLite extensionRegistry);
TBuilder MergeFrom(byte[] data, ExtensionRegistry extensionRegistry);
/// <summary>
/// Parse <paramref name="input"/> as a message of this type and merge
......@@ -219,7 +204,7 @@ namespace Google.ProtocolBuffers {
/// it with the message being built. This is just a small wrapper around
/// MergeFrom(CodedInputStream, ExtensionRegistry).
/// </summary>
TBuilder MergeFrom(Stream input, ExtensionRegistryLite extensionRegistry);
TBuilder MergeFrom(Stream input, ExtensionRegistry extensionRegistry);
#endregion
}
}
......@@ -46,10 +46,18 @@
<ItemGroup>
<Reference Include="mscorlib" />
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="AbstractBuilder.cs" />
<Compile Include="AbstractBuilderLite.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="AbstractMessage.cs" />
<Compile Include="AbstractMessageLite.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="ByteString.cs" />
<Compile Include="Collections\Enumerables.cs" />
<Compile Include="Collections\IPopsicleList.cs" />
......
......@@ -53,6 +53,8 @@
<None Include="Properties\Google.ProtocolBuffers.snk" />
</ItemGroup>
<ItemGroup>
<Compile Include="AbstractBuilderLite.cs" />
<Compile Include="AbstractMessageLite.cs" />
<Compile Include="GeneratedExtensionLite.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ByteString.cs" />
......
......@@ -497,14 +497,13 @@ namespace Google.ProtocolBuffers {
return this;
}
internal void MergeFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistryLite, IBuilder builder) {
internal void MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry, IBuilder builder) {
while (true) {
uint tag = input.ReadTag();
if (tag == 0) {
break;
}
ExtensionRegistry extensionRegistry = (ExtensionRegistry)extensionRegistryLite;
if (!MergeFieldFrom(input, extensionRegistry, builder, tag)) {
// end group tag
break;
......@@ -727,7 +726,7 @@ namespace Google.ProtocolBuffers {
return MergeFrom(data);
}
IBuilderLite IBuilderLite.WeakMergeFrom(ByteString data, ExtensionRegistryLite registry) {
IBuilderLite IBuilderLite.WeakMergeFrom(ByteString data, ExtensionRegistry registry) {
return MergeFrom(data);
}
......@@ -735,7 +734,7 @@ namespace Google.ProtocolBuffers {
return MergeFrom(input);
}
IBuilderLite IBuilderLite.WeakMergeFrom(CodedInputStream input, ExtensionRegistryLite registry) {
IBuilderLite IBuilderLite.WeakMergeFrom(CodedInputStream input, ExtensionRegistry registry) {
return MergeFrom(input);
}
......
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