AbstractBuilder.cs 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using Google.ProtocolBuffers.Descriptors;
  5. using System.Collections;
  6. using System.IO;
  7. namespace Google.ProtocolBuffers {
  8. /// <summary>
  9. /// Implementation of the non-generic IMessage interface as far as possible.
  10. /// TODO(jonskeet): Make this generic, to avoid so much casting in DynamicMessage.
  11. /// </summary>
  12. public abstract class AbstractBuilder : IBuilder {
  13. #region Unimplemented members of IBuilder
  14. public abstract bool IsInitialized { get; }
  15. public abstract IDictionary<FieldDescriptor, object> AllFields { get; }
  16. public abstract object this[FieldDescriptor field] { get; set; }
  17. public abstract MessageDescriptor DescriptorForType { get; }
  18. public abstract int GetRepeatedFieldCount(FieldDescriptor field);
  19. public abstract object this[FieldDescriptor field, int index] { get; set; }
  20. public abstract bool HasField(FieldDescriptor field);
  21. #endregion
  22. #region New abstract methods to be overridden by implementations, allow explicit interface implementation
  23. protected abstract IMessage BuildImpl();
  24. protected abstract IMessage BuildPartialImpl();
  25. protected abstract IBuilder CloneImpl();
  26. protected abstract IMessage DefaultInstanceForTypeImpl { get; }
  27. protected abstract IBuilder ClearFieldImpl(FieldDescriptor field);
  28. protected abstract IBuilder AddRepeatedFieldImpl(FieldDescriptor field, object value);
  29. #endregion
  30. #region Methods simply proxying to the "Impl" methods, explicitly implementing IBuilder
  31. IMessage IBuilder.Build() {
  32. return BuildImpl();
  33. }
  34. IMessage IBuilder.BuildPartial() {
  35. return BuildPartialImpl();
  36. }
  37. IBuilder IBuilder.Clone() {
  38. return CloneImpl();
  39. }
  40. IMessage IBuilder.DefaultInstanceForType {
  41. get { return DefaultInstanceForTypeImpl; }
  42. }
  43. public abstract IBuilder CreateBuilderForField(FieldDescriptor field);
  44. IBuilder IBuilder.ClearField(FieldDescriptor field) {
  45. return ClearFieldImpl(field);
  46. }
  47. IBuilder IBuilder.AddRepeatedField(FieldDescriptor field, object value) {
  48. return AddRepeatedFieldImpl(field, value);
  49. }
  50. #endregion
  51. public virtual IBuilder Clear() {
  52. foreach(FieldDescriptor field in AllFields.Keys) {
  53. ClearFieldImpl(field);
  54. }
  55. return this;
  56. }
  57. public virtual IBuilder MergeFrom(IMessage other) {
  58. if (other.DescriptorForType != DescriptorForType) {
  59. throw new ArgumentException("MergeFrom(Message) can only merge messages of the same type.");
  60. }
  61. // Note: We don't attempt to verify that other's fields have valid
  62. // types. Doing so would be a losing battle. We'd have to verify
  63. // all sub-messages as well, and we'd have to make copies of all of
  64. // them to insure that they don't change after verification (since
  65. // the Message interface itself cannot enforce immutability of
  66. // implementations).
  67. // TODO(jonskeet): Provide a function somewhere called makeDeepCopy()
  68. // which allows people to make secure deep copies of messages.
  69. foreach (KeyValuePair<FieldDescriptor, object> entry in other.AllFields) {
  70. FieldDescriptor field = entry.Key;
  71. if (field.IsRepeated) {
  72. // Concatenate repeated fields
  73. foreach (object element in (IEnumerable) entry.Value) {
  74. AddRepeatedFieldImpl(field, element);
  75. }
  76. } else if (field.MappedType == MappedType.Message) {
  77. // Merge singular messages
  78. IMessage existingValue = (IMessage) this[field];
  79. if (existingValue == existingValue.DefaultInstanceForType) {
  80. this[field] = entry.Value;
  81. } else {
  82. this[field] = existingValue.CreateBuilderForType()
  83. .MergeFrom(existingValue)
  84. .MergeFrom((IMessage) entry.Value)
  85. .Build();
  86. }
  87. } else {
  88. // Overwrite simple values
  89. this[field] = entry.Value;
  90. }
  91. }
  92. return this;
  93. }
  94. IBuilder IBuilder.MergeFrom(CodedInputStream input) {
  95. return MergeFromImpl(input, ExtensionRegistry.Empty);
  96. }
  97. protected virtual IBuilder MergeFromImpl(CodedInputStream input, ExtensionRegistry extensionRegistry) {
  98. UnknownFieldSet.Builder unknownFields = UnknownFieldSet.CreateBuilder(UnknownFields);
  99. FieldSet.MergeFrom(input, unknownFields, extensionRegistry, this);
  100. UnknownFields = unknownFields.Build();
  101. return this;
  102. }
  103. IBuilder IBuilder.MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry) {
  104. return MergeFromImpl(input, extensionRegistry);
  105. }
  106. IBuilder IBuilder.MergeUnknownFields(UnknownFieldSet unknownFields) {
  107. UnknownFields = UnknownFieldSet.CreateBuilder(UnknownFields)
  108. .MergeFrom(unknownFields)
  109. .Build();
  110. return this;
  111. }
  112. IBuilder IBuilder.MergeFrom(ByteString data) {
  113. CodedInputStream input = data.CreateCodedInput();
  114. ((IBuilder)this).MergeFrom(input);
  115. input.CheckLastTagWas(0);
  116. return this;
  117. }
  118. IBuilder IBuilder.MergeFrom(ByteString data, ExtensionRegistry extensionRegistry) {
  119. CodedInputStream input = data.CreateCodedInput();
  120. ((IBuilder)this).MergeFrom(input, extensionRegistry);
  121. input.CheckLastTagWas(0);
  122. return this;
  123. }
  124. IBuilder IBuilder.MergeFrom(byte[] data) {
  125. CodedInputStream input = CodedInputStream.CreateInstance(data);
  126. ((IBuilder)this).MergeFrom(input);
  127. input.CheckLastTagWas(0);
  128. return this;
  129. }
  130. IBuilder IBuilder.MergeFrom(byte[] data, ExtensionRegistry extensionRegistry) {
  131. CodedInputStream input = CodedInputStream.CreateInstance(data);
  132. ((IBuilder)this).MergeFrom(input, extensionRegistry);
  133. input.CheckLastTagWas(0);
  134. return this;
  135. }
  136. IBuilder IBuilder.MergeFrom(Stream input) {
  137. CodedInputStream codedInput = CodedInputStream.CreateInstance(input);
  138. ((IBuilder)this).MergeFrom(codedInput);
  139. codedInput.CheckLastTagWas(0);
  140. return this;
  141. }
  142. IBuilder IBuilder.MergeFrom(Stream input, ExtensionRegistry extensionRegistry) {
  143. CodedInputStream codedInput = CodedInputStream.CreateInstance(input);
  144. ((IBuilder)this).MergeFrom(codedInput, extensionRegistry);
  145. codedInput.CheckLastTagWas(0);
  146. return this;
  147. }
  148. public abstract UnknownFieldSet UnknownFields { get; set; }
  149. public IBuilder SetField(FieldDescriptor field, object value) {
  150. this[field] = value;
  151. return this;
  152. }
  153. public IBuilder SetRepeatedField(FieldDescriptor field, int index, object value) {
  154. this[field, index] = value;
  155. return this;
  156. }
  157. }
  158. }