AbstractBuilder.cs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  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 ClearFieldImpl(FieldDescriptor field);
  27. protected abstract IBuilder AddRepeatedFieldImpl(FieldDescriptor field, object value);
  28. #endregion
  29. #region Methods simply proxying to the "Impl" methods, explicitly implementing IBuilder
  30. IMessage IBuilder.Build() {
  31. return BuildImpl();
  32. }
  33. IMessage IBuilder.BuildPartial() {
  34. return BuildPartialImpl();
  35. }
  36. IBuilder IBuilder.Clone() {
  37. return CloneImpl();
  38. }
  39. IMessage IBuilder.DefaultInstanceForType {
  40. get { return DefaultInstanceForTypeImpl; }
  41. }
  42. public abstract IBuilder CreateBuilderForField(FieldDescriptor field);
  43. IBuilder IBuilder.ClearField(FieldDescriptor field) {
  44. return ClearFieldImpl(field);
  45. }
  46. IBuilder IBuilder.AddRepeatedField(FieldDescriptor field, object value) {
  47. return AddRepeatedFieldImpl(field, value);
  48. }
  49. #endregion
  50. public IBuilder Clear() {
  51. foreach(FieldDescriptor field in AllFields.Keys) {
  52. ClearFieldImpl(field);
  53. }
  54. return this;
  55. }
  56. public virtual IBuilder MergeFrom(IMessage other) {
  57. if (other.DescriptorForType != DescriptorForType) {
  58. throw new ArgumentException("MergeFrom(Message) can only merge messages of the same type.");
  59. }
  60. // Note: We don't attempt to verify that other's fields have valid
  61. // types. Doing so would be a losing battle. We'd have to verify
  62. // all sub-messages as well, and we'd have to make copies of all of
  63. // them to insure that they don't change after verification (since
  64. // the Message interface itself cannot enforce immutability of
  65. // implementations).
  66. // TODO(jonskeet): Provide a function somewhere called makeDeepCopy()
  67. // which allows people to make secure deep copies of messages.
  68. foreach (KeyValuePair<FieldDescriptor, object> entry in AllFields) {
  69. FieldDescriptor field = entry.Key;
  70. if (field.IsRepeated) {
  71. // Concatenate repeated fields
  72. foreach (object element in (IEnumerable) entry.Value) {
  73. AddRepeatedFieldImpl(field, element);
  74. }
  75. } else if (field.MappedType == MappedType.Message) {
  76. // Merge singular messages
  77. IMessage existingValue = (IMessage) this[field];
  78. if (existingValue == existingValue.DefaultInstanceForType) {
  79. this[field] = entry.Value;
  80. } else {
  81. this[field] = existingValue.CreateBuilderForType()
  82. .MergeFrom(existingValue)
  83. .MergeFrom((IMessage) entry.Value)
  84. .Build();
  85. }
  86. } else {
  87. // Overwrite simple values
  88. this[field] = entry.Value;
  89. }
  90. }
  91. return this;
  92. }
  93. IBuilder IBuilder.MergeFrom(CodedInputStream input) {
  94. return ((IBuilder)this).MergeFrom(input, ExtensionRegistry.Empty);
  95. }
  96. IBuilder IBuilder.MergeFrom(CodedInputStream input, ExtensionRegistry extensionRegistry) {
  97. UnknownFieldSet.Builder unknownFields = UnknownFieldSet.CreateBuilder(UnknownFields);
  98. FieldSet.MergeFrom(input, unknownFields, extensionRegistry, this);
  99. UnknownFields = unknownFields.Build();
  100. return this;
  101. }
  102. IBuilder IBuilder.MergeUnknownFields(UnknownFieldSet unknownFields) {
  103. UnknownFields = UnknownFieldSet.CreateBuilder(UnknownFields)
  104. .MergeFrom(unknownFields)
  105. .Build();
  106. return this;
  107. }
  108. public UnknownFieldSet UnknownFields { get; set; }
  109. IBuilder IBuilder.MergeFrom(ByteString data) {
  110. CodedInputStream input = data.CreateCodedInput();
  111. ((IBuilder)this).MergeFrom(input);
  112. input.CheckLastTagWas(0);
  113. return this;
  114. }
  115. IBuilder IBuilder.MergeFrom(ByteString data, ExtensionRegistry extensionRegistry) {
  116. CodedInputStream input = data.CreateCodedInput();
  117. ((IBuilder)this).MergeFrom(input, extensionRegistry);
  118. input.CheckLastTagWas(0);
  119. return this;
  120. }
  121. IBuilder IBuilder.MergeFrom(byte[] data) {
  122. CodedInputStream input = CodedInputStream.CreateInstance(data);
  123. ((IBuilder)this).MergeFrom(input);
  124. input.CheckLastTagWas(0);
  125. return this;
  126. }
  127. IBuilder IBuilder.MergeFrom(byte[] data, ExtensionRegistry extensionRegistry) {
  128. CodedInputStream input = CodedInputStream.CreateInstance(data);
  129. ((IBuilder)this).MergeFrom(input, extensionRegistry);
  130. input.CheckLastTagWas(0);
  131. return this;
  132. }
  133. IBuilder IBuilder.MergeFrom(Stream input) {
  134. CodedInputStream codedInput = CodedInputStream.CreateInstance(input);
  135. ((IBuilder)this).MergeFrom(codedInput);
  136. codedInput.CheckLastTagWas(0);
  137. return this;
  138. }
  139. IBuilder IBuilder.MergeFrom(Stream input, ExtensionRegistry extensionRegistry) {
  140. CodedInputStream codedInput = CodedInputStream.CreateInstance(input);
  141. ((IBuilder) this).MergeFrom(codedInput, extensionRegistry);
  142. codedInput.CheckLastTagWas(0);
  143. return this;
  144. }
  145. }
  146. }