AbstractBuilder.cs 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. // Protocol Buffers - Google's data interchange format
  2. // Copyright 2008 Google Inc.
  3. // http://code.google.com/p/protobuf/
  4. //
  5. // Licensed under the Apache License, Version 2.0 (the "License");
  6. // you may not use this file except in compliance with the License.
  7. // You may obtain a copy of the License at
  8. //
  9. // http://www.apache.org/licenses/LICENSE-2.0
  10. //
  11. // Unless required by applicable law or agreed to in writing, software
  12. // distributed under the License is distributed on an "AS IS" BASIS,
  13. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. // See the License for the specific language governing permissions and
  15. // limitations under the License.
  16. using System;
  17. using System.Collections;
  18. using System.Collections.Generic;
  19. using System.IO;
  20. using Google.ProtocolBuffers.Descriptors;
  21. namespace Google.ProtocolBuffers {
  22. /// <summary>
  23. /// Implementation of the non-generic IMessage interface as far as possible.
  24. /// </summary>
  25. public abstract class AbstractBuilder<TMessage, TBuilder> : IBuilder<TMessage, TBuilder>
  26. where TMessage : AbstractMessage<TMessage, TBuilder>
  27. where TBuilder : AbstractBuilder<TMessage, TBuilder> {
  28. protected abstract TBuilder ThisBuilder { get; }
  29. #region Unimplemented members of IBuilder
  30. public abstract UnknownFieldSet UnknownFields { get; set; }
  31. public abstract TBuilder MergeFrom(TMessage other);
  32. public abstract bool IsInitialized { get; }
  33. public abstract IDictionary<FieldDescriptor, object> AllFields { get; }
  34. public abstract object this[FieldDescriptor field] { get; set; }
  35. public abstract MessageDescriptor DescriptorForType { get; }
  36. public abstract int GetRepeatedFieldCount(FieldDescriptor field);
  37. public abstract object this[FieldDescriptor field, int index] { get; set; }
  38. public abstract bool HasField(FieldDescriptor field);
  39. public abstract TMessage Build();
  40. public abstract TMessage BuildPartial();
  41. public abstract TBuilder Clone();
  42. public abstract TMessage DefaultInstanceForType { get; }
  43. public abstract IBuilder CreateBuilderForField(FieldDescriptor field);
  44. public abstract TBuilder ClearField(FieldDescriptor field);
  45. public abstract TBuilder AddRepeatedField(FieldDescriptor field, object value);
  46. #endregion
  47. #region Implementation of methods which don't require type parameter information
  48. public IMessage WeakBuild() {
  49. return Build();
  50. }
  51. public IBuilder WeakAddRepeatedField(FieldDescriptor field, object value) {
  52. return AddRepeatedField(field, value);
  53. }
  54. public IBuilder WeakClear() {
  55. return Clear();
  56. }
  57. public IBuilder WeakMergeFrom(IMessage message) {
  58. return MergeFrom(message);
  59. }
  60. public IBuilder WeakMergeFrom(CodedInputStream input) {
  61. return MergeFrom(input);
  62. }
  63. public IBuilder WeakMergeFrom(CodedInputStream input, ExtensionRegistry registry) {
  64. return MergeFrom(input, registry);
  65. }
  66. public IBuilder WeakMergeFrom(ByteString data) {
  67. return MergeFrom(data);
  68. }
  69. public IBuilder WeakMergeFrom(ByteString data, ExtensionRegistry registry) {
  70. return MergeFrom(data, registry);
  71. }
  72. public IMessage WeakBuildPartial() {
  73. return BuildPartial();
  74. }
  75. public IBuilder WeakClone() {
  76. return Clone();
  77. }
  78. public IMessage WeakDefaultInstanceForType {
  79. get { return DefaultInstanceForType; }
  80. }
  81. public IBuilder WeakClearField(FieldDescriptor field) {
  82. return ClearField(field);
  83. }
  84. #endregion
  85. public TBuilder SetUnknownFields(UnknownFieldSet fields) {
  86. UnknownFields = fields;
  87. return ThisBuilder;
  88. }
  89. public virtual TBuilder Clear() {
  90. foreach(FieldDescriptor field in AllFields.Keys) {
  91. ClearField(field);
  92. }
  93. return ThisBuilder;
  94. }
  95. public virtual TBuilder MergeFrom(IMessage other) {
  96. if (other.DescriptorForType != DescriptorForType) {
  97. throw new ArgumentException("MergeFrom(IMessage) can only merge messages of the same type.");
  98. }
  99. // Note: We don't attempt to verify that other's fields have valid
  100. // types. Doing so would be a losing battle. We'd have to verify
  101. // all sub-messages as well, and we'd have to make copies of all of
  102. // them to insure that they don't change after verification (since
  103. // the Message interface itself cannot enforce immutability of
  104. // implementations).
  105. // TODO(jonskeet): Provide a function somewhere called MakeDeepCopy()
  106. // which allows people to make secure deep copies of messages.
  107. foreach (KeyValuePair<FieldDescriptor, object> entry in other.AllFields) {
  108. FieldDescriptor field = entry.Key;
  109. if (field.IsRepeated) {
  110. // Concatenate repeated fields
  111. foreach (object element in (IEnumerable) entry.Value) {
  112. AddRepeatedField(field, element);
  113. }
  114. } else if (field.MappedType == MappedType.Message) {
  115. // Merge singular messages
  116. IMessage existingValue = (IMessage) this[field];
  117. if (existingValue == existingValue.WeakDefaultInstanceForType) {
  118. this[field] = entry.Value;
  119. } else {
  120. this[field] = existingValue.WeakCreateBuilderForType()
  121. .WeakMergeFrom(existingValue)
  122. .WeakMergeFrom((IMessage) entry.Value)
  123. .WeakBuild();
  124. }
  125. } else {
  126. // Overwrite simple values
  127. this[field] = entry.Value;
  128. }
  129. }
  130. return ThisBuilder;
  131. }
  132. public virtual TBuilder MergeFrom(CodedInputStream input) {
  133. return MergeFrom(input, ExtensionRegistry.Empty);
  134. }
  135. public virtual TBuilder MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry) {
  136. UnknownFieldSet.Builder unknownFields = UnknownFieldSet.CreateBuilder(UnknownFields);
  137. unknownFields.MergeFrom(input, extensionRegistry, this);
  138. UnknownFields = unknownFields.Build();
  139. return ThisBuilder;
  140. }
  141. public virtual TBuilder MergeUnknownFields(UnknownFieldSet unknownFields) {
  142. UnknownFields = UnknownFieldSet.CreateBuilder(UnknownFields)
  143. .MergeFrom(unknownFields)
  144. .Build();
  145. return ThisBuilder;
  146. }
  147. public virtual TBuilder MergeFrom(ByteString data) {
  148. CodedInputStream input = data.CreateCodedInput();
  149. MergeFrom(input);
  150. input.CheckLastTagWas(0);
  151. return ThisBuilder;
  152. }
  153. public virtual TBuilder MergeFrom(ByteString data, ExtensionRegistry extensionRegistry) {
  154. CodedInputStream input = data.CreateCodedInput();
  155. MergeFrom(input, extensionRegistry);
  156. input.CheckLastTagWas(0);
  157. return ThisBuilder;
  158. }
  159. public virtual TBuilder MergeFrom(byte[] data) {
  160. CodedInputStream input = CodedInputStream.CreateInstance(data);
  161. MergeFrom(input);
  162. input.CheckLastTagWas(0);
  163. return ThisBuilder;
  164. }
  165. public virtual TBuilder MergeFrom(byte[] data, ExtensionRegistry extensionRegistry) {
  166. CodedInputStream input = CodedInputStream.CreateInstance(data);
  167. MergeFrom(input, extensionRegistry);
  168. input.CheckLastTagWas(0);
  169. return ThisBuilder;
  170. }
  171. public virtual TBuilder MergeFrom(Stream input) {
  172. CodedInputStream codedInput = CodedInputStream.CreateInstance(input);
  173. MergeFrom(codedInput);
  174. codedInput.CheckLastTagWas(0);
  175. return ThisBuilder;
  176. }
  177. public virtual TBuilder MergeFrom(Stream input, ExtensionRegistry extensionRegistry) {
  178. CodedInputStream codedInput = CodedInputStream.CreateInstance(input);
  179. MergeFrom(codedInput, extensionRegistry);
  180. codedInput.CheckLastTagWas(0);
  181. return ThisBuilder;
  182. }
  183. public virtual IBuilder SetField(FieldDescriptor field, object value) {
  184. this[field] = value;
  185. return ThisBuilder;
  186. }
  187. public virtual IBuilder SetRepeatedField(FieldDescriptor field, int index, object value) {
  188. this[field, index] = value;
  189. return ThisBuilder;
  190. }
  191. }
  192. }