ExtendableMessage.cs 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using Google.ProtocolBuffers.Descriptors;
  5. using Google.ProtocolBuffers.Collections;
  6. namespace Google.ProtocolBuffers {
  7. public abstract class ExtendableMessage<TMessage,TBuilder> : GeneratedMessage<TMessage,TBuilder>
  8. where TMessage : GeneratedMessage<TMessage, TBuilder>
  9. where TBuilder : IBuilder<TMessage> {
  10. protected ExtendableMessage() {}
  11. private readonly FieldSet extensions = FieldSet.CreateFieldSet();
  12. /// <summary>
  13. /// Checks if a singular extension is present.
  14. /// </summary>
  15. public bool HasExtension(GeneratedExtension<TMessage, TBuilder> extension) {
  16. return extensions.HasField(extension.Descriptor);
  17. }
  18. /// <summary>
  19. /// Returns the number of elements in a repeated extension.
  20. /// </summary>
  21. public int GetExtensionCount<TExtension>(GeneratedExtension<TMessage, IList<TExtension>> extension) {
  22. return extensions.GetRepeatedFieldCount(extension.Descriptor);
  23. }
  24. /// <summary>
  25. /// Returns the value of an extension.
  26. /// </summary>
  27. public TExtension GetExtension<TExtension>(GeneratedExtension<TMessage, TExtension> extension) {
  28. object value = extensions[extension.Descriptor];
  29. if (value == null) {
  30. return (TExtension) extension.MessageDefaultInstance;
  31. } else {
  32. return (TExtension) extension.FromReflectionType(value);
  33. }
  34. }
  35. /// <summary>
  36. /// Returns one element of a repeated extension.
  37. /// </summary>
  38. public TExtension GetExtension<TExtension>(GeneratedExtension<TMessage, IList<TExtension>> extension, int index) {
  39. return (TExtension) extension.SingularFromReflectionType(extensions[extension.Descriptor, index]);
  40. }
  41. /// <summary>
  42. /// Called by subclasses to check if all extensions are initialized.
  43. /// </summary>
  44. protected bool ExtensionsAreInitialized {
  45. get { return extensions.IsInitialized; }
  46. }
  47. #region Reflection
  48. public override IDictionary<FieldDescriptor, object> AllFields {
  49. get {
  50. IDictionary<FieldDescriptor, object> result = GetMutableFieldMap();
  51. foreach(KeyValuePair<FieldDescriptor, object> entry in extensions.AllFields) {
  52. result[entry.Key] = entry.Value;
  53. }
  54. return Dictionaries.AsReadOnly(result);
  55. }
  56. }
  57. public override bool HasField(FieldDescriptor field) {
  58. if (field.IsExtension) {
  59. VerifyContainingType(field);
  60. return extensions.HasField(field);
  61. } else {
  62. return base.HasField(field);
  63. }
  64. }
  65. public override object this[FieldDescriptor field] {
  66. get {
  67. if (field.IsExtension) {
  68. VerifyContainingType(field);
  69. object value = extensions[field];
  70. if (value == null) {
  71. // Lacking an ExtensionRegistry, we have no way to determine the
  72. // extension's real type, so we return a DynamicMessage.
  73. // TODO(jonskeet): Work out what this means
  74. return DynamicMessage.GetDefaultInstance(field.MessageType);
  75. } else {
  76. return value;
  77. }
  78. } else {
  79. return base[field];
  80. }
  81. }
  82. }
  83. public override int GetRepeatedFieldCount(FieldDescriptor field) {
  84. if (field.IsExtension) {
  85. VerifyContainingType(field);
  86. return extensions.GetRepeatedFieldCount(field);
  87. } else {
  88. return base.GetRepeatedFieldCount(field);
  89. }
  90. }
  91. public override object this[FieldDescriptor field, int index] {
  92. get {
  93. if (field.IsExtension) {
  94. VerifyContainingType(field);
  95. return extensions[field, index];
  96. } else {
  97. return base[field, index];
  98. }
  99. }
  100. }
  101. private void VerifyContainingType(FieldDescriptor field) {
  102. if (field.ContainingType != DescriptorForType) {
  103. throw new ArgumentException("FieldDescriptor does not match message type.");
  104. }
  105. }
  106. #endregion
  107. /// <summary>
  108. /// Used by subclasses to serialize extensions. Extension ranges may be
  109. /// interleaves with field numbers, but we must write them in canonical
  110. /// (sorted by field number) order. This class helps us to write individual
  111. /// ranges of extensions at once.
  112. ///
  113. /// TODO(jonskeet): See if we can improve this in terms of readability.
  114. /// </summary>
  115. protected class ExtensionWriter {
  116. readonly IEnumerator<KeyValuePair<FieldDescriptor, object>> iterator;
  117. readonly FieldSet extensions;
  118. KeyValuePair<FieldDescriptor, object>? next = null;
  119. internal ExtensionWriter(ExtendableMessage<TMessage, TBuilder> message) {
  120. extensions = message.extensions;
  121. iterator = message.extensions.GetEnumerator();
  122. if (iterator.MoveNext()) {
  123. next = iterator.Current;
  124. }
  125. }
  126. public void WriteUntil(int end, CodedOutputStream output) {
  127. while (next != null && next.Value.Key.FieldNumber < end) {
  128. extensions.WriteField(next.Value.Key, next.Value.Value, output);
  129. if (iterator.MoveNext()) {
  130. next = iterator.Current;
  131. } else {
  132. next = null;
  133. }
  134. }
  135. }
  136. }
  137. protected ExtensionWriter CreateExtensionWriter(ExtendableMessage<TMessage, TBuilder> message) {
  138. return new ExtensionWriter(message);
  139. }
  140. /// <summary>
  141. /// Called by subclasses to compute the size of extensions.
  142. /// </summary>
  143. protected int ExtensionsSerializedSize {
  144. get { return extensions.SerializedSize; }
  145. }
  146. }
  147. }