diff options
Diffstat (limited to 'src/ProtocolBuffers/AbstractBuilder.cs')
-rw-r--r-- | src/ProtocolBuffers/AbstractBuilder.cs | 234 |
1 files changed, 66 insertions, 168 deletions
diff --git a/src/ProtocolBuffers/AbstractBuilder.cs b/src/ProtocolBuffers/AbstractBuilder.cs index a60ff0aa..0d1279c7 100644 --- a/src/ProtocolBuffers/AbstractBuilder.cs +++ b/src/ProtocolBuffers/AbstractBuilder.cs @@ -42,93 +42,57 @@ namespace Google.ProtocolBuffers { /// <summary> /// Implementation of the non-generic IMessage interface as far as possible. /// </summary> - public abstract class AbstractBuilder<TMessage, TBuilder> : IBuilder<TMessage, TBuilder> + public abstract class AbstractBuilder<TMessage, TBuilder> : AbstractBuilderLite<TMessage, TBuilder>, IBuilder<TMessage, TBuilder> where TMessage : AbstractMessage<TMessage, TBuilder> where TBuilder : AbstractBuilder<TMessage, TBuilder> { - protected abstract TBuilder ThisBuilder { get; } - #region Unimplemented members of IBuilder public abstract UnknownFieldSet UnknownFields { get; set; } - public abstract TBuilder MergeFrom(TMessage other); - public abstract bool IsInitialized { get; } public abstract IDictionary<FieldDescriptor, object> AllFields { get; } public abstract object this[FieldDescriptor field] { get; set; } public abstract MessageDescriptor DescriptorForType { get; } public abstract int GetRepeatedFieldCount(FieldDescriptor field); public abstract object this[FieldDescriptor field, int index] { get; set; } public abstract bool HasField(FieldDescriptor field); - public abstract TMessage Build(); - public abstract TMessage BuildPartial(); - public abstract TBuilder Clone(); - public abstract TMessage DefaultInstanceForType { get; } public abstract IBuilder CreateBuilderForField(FieldDescriptor field); public abstract TBuilder ClearField(FieldDescriptor field); public abstract TBuilder AddRepeatedField(FieldDescriptor field, object value); #endregion - #region Implementation of methods which don't require type parameter information - public IMessage WeakBuild() { - return Build(); - } - - public IBuilder WeakAddRepeatedField(FieldDescriptor field, object value) { - return AddRepeatedField(field, value); - } - - public IBuilder WeakClear() { - return Clear(); - } - - public IBuilder WeakMergeFrom(IMessage message) { - return MergeFrom(message); - } - - public IBuilder WeakMergeFrom(CodedInputStream input) { - return MergeFrom(input); - } - - public IBuilder WeakMergeFrom(CodedInputStream input, ExtensionRegistry registry) { - return MergeFrom(input, registry); - } - - public IBuilder WeakMergeFrom(ByteString data) { - return MergeFrom(data); - } - - public IBuilder WeakMergeFrom(ByteString data, ExtensionRegistry registry) { - return MergeFrom(data, registry); - } - - public IMessage WeakBuildPartial() { - return BuildPartial(); - } - - public IBuilder WeakClone() { - return Clone(); - } - - public IMessage WeakDefaultInstanceForType { - get { return DefaultInstanceForType; } - } - - public IBuilder WeakClearField(FieldDescriptor field) { - return ClearField(field); - } - #endregion - public TBuilder SetUnknownFields(UnknownFieldSet fields) { UnknownFields = fields; return ThisBuilder; } - public virtual TBuilder Clear() { + public override TBuilder Clear() { foreach(FieldDescriptor field in AllFields.Keys) { ClearField(field); } return ThisBuilder; } + public sealed override TBuilder MergeFrom(IMessageLite other) { + if (other is IMessage) { + return MergeFrom((IMessage) other); + } + throw new ArgumentException("MergeFrom(Message) can only merge messages of the same type."); + } + + /// <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> + public abstract TBuilder MergeFrom(TMessage other); + public virtual TBuilder MergeFrom(IMessage other) { if (other.DescriptorForType != DescriptorForType) { throw new ArgumentException("MergeFrom(IMessage) can only merge messages of the same type."); @@ -151,13 +115,13 @@ namespace Google.ProtocolBuffers { } } else if (field.MappedType == MappedType.Message) { // Merge singular messages - IMessage existingValue = (IMessage) this[field]; + IMessageLite existingValue = (IMessageLite)this[field]; if (existingValue == existingValue.WeakDefaultInstanceForType) { this[field] = entry.Value; } else { this[field] = existingValue.WeakCreateBuilderForType() .WeakMergeFrom(existingValue) - .WeakMergeFrom((IMessage) entry.Value) + .WeakMergeFrom((IMessageLite)entry.Value) .WeakBuild(); } } else { @@ -165,14 +129,14 @@ namespace Google.ProtocolBuffers { this[field] = entry.Value; } } - return ThisBuilder; - } - public virtual TBuilder MergeFrom(CodedInputStream input) { - return MergeFrom(input, ExtensionRegistry.Empty); + //Fix for unknown fields not merging, see java's AbstractMessage.Builder<T> line 236 + MergeUnknownFields(other.UnknownFields); + + return ThisBuilder; } - public virtual TBuilder MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry) { + public override TBuilder MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry) { UnknownFieldSet.Builder unknownFields = UnknownFieldSet.CreateBuilder(UnknownFields); unknownFields.MergeFrom(input, extensionRegistry, this); UnknownFields = unknownFields.Build(); @@ -186,131 +150,65 @@ namespace Google.ProtocolBuffers { return ThisBuilder; } - public virtual TBuilder MergeFrom(ByteString data) { - CodedInputStream input = data.CreateCodedInput(); - MergeFrom(input); - input.CheckLastTagWas(0); + public virtual IBuilder SetField(FieldDescriptor field, object value) { + this[field] = value; return ThisBuilder; } - public virtual TBuilder MergeFrom(ByteString data, ExtensionRegistry extensionRegistry) { - CodedInputStream input = data.CreateCodedInput(); - MergeFrom(input, extensionRegistry); - input.CheckLastTagWas(0); + public virtual IBuilder SetRepeatedField(FieldDescriptor field, int index, object value) { + this[field, index] = value; return ThisBuilder; - } + } - public virtual TBuilder MergeFrom(byte[] data) { - CodedInputStream input = CodedInputStream.CreateInstance(data); - MergeFrom(input); - input.CheckLastTagWas(0); - return ThisBuilder; - } + #region Explicit Implementations - public virtual TBuilder MergeFrom(byte[] data, ExtensionRegistry extensionRegistry) { - CodedInputStream input = CodedInputStream.CreateInstance(data); - MergeFrom(input, extensionRegistry); - input.CheckLastTagWas(0); - return ThisBuilder; + IMessage IBuilder.WeakBuild() { + return Build(); } - public virtual TBuilder MergeFrom(Stream input) { - CodedInputStream codedInput = CodedInputStream.CreateInstance(input); - MergeFrom(codedInput); - codedInput.CheckLastTagWas(0); - return ThisBuilder; + IBuilder IBuilder.WeakAddRepeatedField(FieldDescriptor field, object value) { + return AddRepeatedField(field, value); } - public virtual TBuilder MergeFrom(Stream input, ExtensionRegistry extensionRegistry) { - CodedInputStream codedInput = CodedInputStream.CreateInstance(input); - MergeFrom(codedInput, extensionRegistry); - codedInput.CheckLastTagWas(0); - return ThisBuilder; + IBuilder IBuilder.WeakClear() { + return Clear(); } - public TBuilder MergeDelimitedFrom(Stream input, ExtensionRegistry extensionRegistry) { - int size = (int) CodedInputStream.ReadRawVarint32(input); - Stream limitedStream = new LimitedInputStream(input, size); - return MergeFrom(limitedStream, extensionRegistry); + IBuilder IBuilder.WeakMergeFrom(IMessage message) { + return MergeFrom(message); } - public TBuilder MergeDelimitedFrom(Stream input) { - return MergeDelimitedFrom(input, ExtensionRegistry.Empty); + IBuilder IBuilder.WeakMergeFrom(CodedInputStream input) { + return MergeFrom(input); } - public virtual IBuilder SetField(FieldDescriptor field, object value) { - this[field] = value; - return ThisBuilder; + IBuilder IBuilder.WeakMergeFrom(CodedInputStream input, ExtensionRegistry registry) { + return MergeFrom(input, registry); } - public virtual IBuilder SetRepeatedField(FieldDescriptor field, int index, object value) { - this[field, index] = value; - return ThisBuilder; + IBuilder IBuilder.WeakMergeFrom(ByteString data) { + return MergeFrom(data); } - /// <summary> - /// Stream implementation which proxies another stream, only allowing a certain amount - /// of data to be read. Note that this is only used to read delimited streams, so it - /// doesn't attempt to implement everything. - /// </summary> - private class LimitedInputStream : Stream { - - private readonly Stream proxied; - private int bytesLeft; - - internal LimitedInputStream(Stream proxied, int size) { - this.proxied = proxied; - bytesLeft = size; - } - - public override bool CanRead { - get { return true; } - } - - public override bool CanSeek { - get { return false; } - } - - public override bool CanWrite { - get { return false; } - } - - public override void Flush() { - } - - public override long Length { - get { throw new NotImplementedException(); } - } - - public override long Position { - get { - throw new NotImplementedException(); - } - set { - throw new NotImplementedException(); - } - } + IBuilder IBuilder.WeakMergeFrom(ByteString data, ExtensionRegistry registry) { + return MergeFrom(data, registry); + } - public override int Read(byte[] buffer, int offset, int count) { - if (bytesLeft > 0) { - int bytesRead = proxied.Read(buffer, offset, Math.Min(bytesLeft, count)); - bytesLeft -= bytesRead; - return bytesRead; - } - return 0; - } + IMessage IBuilder.WeakBuildPartial() { + return BuildPartial(); + } - public override long Seek(long offset, SeekOrigin origin) { - throw new NotImplementedException(); - } + IBuilder IBuilder.WeakClone() { + return Clone(); + } - public override void SetLength(long value) { - throw new NotImplementedException(); - } + IMessage IBuilder.WeakDefaultInstanceForType { + get { return DefaultInstanceForType; } + } - public override void Write(byte[] buffer, int offset, int count) { - throw new NotImplementedException(); - } + IBuilder IBuilder.WeakClearField(FieldDescriptor field) { + return ClearField(field); } + #endregion } } |