AbstractBuilder.cs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  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. /// </summary>
  11. public abstract class AbstractBuilder : IBuilder {
  12. #region Unimplemented members of IBuilder
  13. public abstract bool Initialized { get; }
  14. public abstract IDictionary<FieldDescriptor, object> AllFields { get; }
  15. public abstract object this[FieldDescriptor field] { get; set; }
  16. public abstract MessageDescriptor DescriptorForType { get; }
  17. public abstract int GetRepeatedFieldCount(FieldDescriptor field);
  18. public abstract object this[FieldDescriptor field, int index] { get; set; }
  19. public abstract bool HasField(FieldDescriptor field);
  20. #endregion
  21. #region New abstract methods to be overridden by implementations, allow explicit interface implementation
  22. protected abstract IMessage BuildImpl();
  23. protected abstract IMessage BuildPartialImpl();
  24. protected abstract IBuilder CloneImpl();
  25. protected abstract IMessage DefaultInstanceForTypeImpl { get; }
  26. protected abstract IBuilder NewBuilderForFieldImpl(FieldDescriptor field);
  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. IBuilder IBuilder.NewBuilderForField(FieldDescriptor field) {
  44. return NewBuilderForFieldImpl(field);
  45. }
  46. IBuilder IBuilder.ClearField(FieldDescriptor field) {
  47. return ClearFieldImpl(field);
  48. }
  49. IBuilder IBuilder.AddRepeatedField(FieldDescriptor field, object value) {
  50. return AddRepeatedFieldImpl(field, value);
  51. }
  52. #endregion
  53. public IBuilder Clear() {
  54. foreach(FieldDescriptor field in AllFields.Keys) {
  55. ClearFieldImpl(field);
  56. }
  57. return this;
  58. }
  59. public IBuilder MergeFrom(IMessage other) {
  60. if (other.DescriptorForType != DescriptorForType) {
  61. throw new ArgumentException("MergeFrom(Message) can only merge messages of the same type.");
  62. }
  63. // Note: We don't attempt to verify that other's fields have valid
  64. // types. Doing so would be a losing battle. We'd have to verify
  65. // all sub-messages as well, and we'd have to make copies of all of
  66. // them to insure that they don't change after verification (since
  67. // the Message interface itself cannot enforce immutability of
  68. // implementations).
  69. // TODO(jonskeet): Provide a function somewhere called makeDeepCopy()
  70. // which allows people to make secure deep copies of messages.
  71. foreach (KeyValuePair<FieldDescriptor, object> entry in AllFields) {
  72. FieldDescriptor field = entry.Key;
  73. if (field.IsRepeated) {
  74. // Concatenate repeated fields
  75. foreach (object element in (IEnumerable) entry.Value) {
  76. AddRepeatedFieldImpl(field, element);
  77. }
  78. } else if (field.MappedType == MappedType.Message) {
  79. // Merge singular messages
  80. IMessage existingValue = (IMessage) this[field];
  81. if (existingValue == existingValue.DefaultInstanceForType) {
  82. this[field] = entry.Value;
  83. } else {
  84. this[field] = existingValue.CreateBuilderForType()
  85. .MergeFrom(existingValue)
  86. .MergeFrom((IMessage) entry.Value)
  87. .Build();
  88. }
  89. } else {
  90. // Overwrite simple values
  91. this[field] = entry.Value;
  92. }
  93. }
  94. return this;
  95. }
  96. public IBuilder MergeFrom(CodedInputStream input) {
  97. return MergeFrom(input, ExtensionRegistry.Empty);
  98. }
  99. public IBuilder MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry) {
  100. UnknownFieldSet.Builder unknownFields = UnknownFieldSet.CreateBuilder(UnknownFields);
  101. FieldSet.MergeFrom(input, unknownFields, extensionRegistry, this);
  102. UnknownFields = unknownFields.Build();
  103. return this;
  104. }
  105. public IBuilder MergeUnknownFields(UnknownFieldSet unknownFields) {
  106. UnknownFields = UnknownFieldSet.CreateBuilder(UnknownFields)
  107. .MergeFrom(unknownFields)
  108. .Build();
  109. return this;
  110. }
  111. public UnknownFieldSet UnknownFields { get; set; }
  112. public IBuilder MergeFrom(ByteString data) {
  113. CodedInputStream input = data.CreateCodedInput();
  114. MergeFrom(input);
  115. input.CheckLastTagWas(0);
  116. return this;
  117. }
  118. public IBuilder MergeFrom(ByteString data, ExtensionRegistry extensionRegistry) {
  119. CodedInputStream input = data.CreateCodedInput();
  120. MergeFrom(input, extensionRegistry);
  121. input.CheckLastTagWas(0);
  122. return this;
  123. }
  124. public IBuilder MergeFrom(byte[] data) {
  125. CodedInputStream input = CodedInputStream.CreateInstance(data);
  126. MergeFrom(input);
  127. input.CheckLastTagWas(0);
  128. return this;
  129. }
  130. public IBuilder MergeFrom(byte[] data, ExtensionRegistry extensionRegistry) {
  131. CodedInputStream input = CodedInputStream.CreateInstance(data);
  132. MergeFrom(input, extensionRegistry);
  133. input.CheckLastTagWas(0);
  134. return this;
  135. }
  136. public IBuilder MergeFrom(Stream input) {
  137. CodedInputStream codedInput = CodedInputStream.CreateInstance(input);
  138. MergeFrom(codedInput);
  139. codedInput.CheckLastTagWas(0);
  140. return this;
  141. }
  142. public IBuilder MergeFrom(Stream input, ExtensionRegistry extensionRegistry) {
  143. CodedInputStream codedInput = CodedInputStream.CreateInstance(input);
  144. MergeFrom(codedInput, extensionRegistry);
  145. codedInput.CheckLastTagWas(0);
  146. return this;
  147. }
  148. }
  149. }