GeneratedExtensionLite.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. #region Copyright notice and license
  2. // Protocol Buffers - Google's data interchange format
  3. // Copyright 2008 Google Inc. All rights reserved.
  4. // http://github.com/jskeet/dotnet-protobufs/
  5. // Original C++/Java/Python code:
  6. // http://code.google.com/p/protobuf/
  7. //
  8. // Redistribution and use in source and binary forms, with or without
  9. // modification, are permitted provided that the following conditions are
  10. // met:
  11. //
  12. // * Redistributions of source code must retain the above copyright
  13. // notice, this list of conditions and the following disclaimer.
  14. // * Redistributions in binary form must reproduce the above
  15. // copyright notice, this list of conditions and the following disclaimer
  16. // in the documentation and/or other materials provided with the
  17. // distribution.
  18. // * Neither the name of Google Inc. nor the names of its
  19. // contributors may be used to endorse or promote products derived from
  20. // this software without specific prior written permission.
  21. //
  22. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  23. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  24. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  25. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  26. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  27. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  28. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  29. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  30. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  31. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  32. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  33. #endregion
  34. using System;
  35. using System.Collections;
  36. using System.Collections.Generic;
  37. using Google.ProtocolBuffers.Collections;
  38. using Google.ProtocolBuffers.Descriptors;
  39. namespace Google.ProtocolBuffers {
  40. public interface IGeneratedExtensionLite {
  41. int Number { get; }
  42. object ContainingType { get; }
  43. IMessageLite MessageDefaultInstance { get; }
  44. IFieldDescriptorLite Descriptor { get; }
  45. }
  46. public class ExtensionDescriptorLite : IFieldDescriptorLite {
  47. private readonly string fullName;
  48. private readonly IEnumLiteMap enumTypeMap;
  49. private readonly int number;
  50. private readonly FieldType type;
  51. private readonly bool isRepeated;
  52. private readonly bool isPacked;
  53. private readonly MappedType mapType;
  54. private readonly object defaultValue;
  55. public ExtensionDescriptorLite(string fullName, IEnumLiteMap enumTypeMap, int number, FieldType type, object defaultValue, bool isRepeated, bool isPacked) {
  56. this.fullName = fullName;
  57. this.enumTypeMap = enumTypeMap;
  58. this.number = number;
  59. this.type = type;
  60. this.mapType = FieldMappingAttribute.MappedTypeFromFieldType(type);
  61. this.isRepeated = isRepeated;
  62. this.isPacked = isPacked;
  63. this.defaultValue = defaultValue;
  64. }
  65. public string FullName { get { return fullName; } }
  66. public bool IsRepeated {
  67. get { return isRepeated; }
  68. }
  69. public bool IsRequired {
  70. get { return false; }
  71. }
  72. public bool IsPacked {
  73. get { return isPacked; }
  74. }
  75. public bool IsExtension {
  76. get { return true; }
  77. }
  78. /// <summary>
  79. /// This is not supported and assertions are made to ensure this does not exist on extensions of Lite types
  80. /// </summary>
  81. public bool MessageSetWireFormat {
  82. get { return false; }
  83. }
  84. public int FieldNumber {
  85. get { return number; }
  86. }
  87. public IEnumLiteMap EnumType {
  88. get { return enumTypeMap; }
  89. }
  90. public FieldType FieldType {
  91. get { return type; }
  92. }
  93. public MappedType MappedType {
  94. get { return mapType; }
  95. }
  96. public object DefaultValue {
  97. get { return defaultValue; }
  98. }
  99. public int CompareTo(IFieldDescriptorLite other) {
  100. return FieldNumber.CompareTo(other.FieldNumber);
  101. }
  102. }
  103. public class GeneratedRepeatExtensionLite<TContainingType, TExtensionType> : GeneratedExtensionLite<TContainingType, IList<TExtensionType>>
  104. where TContainingType : IMessageLite {
  105. public GeneratedRepeatExtensionLite(string fullName, TContainingType containingTypeDefaultInstance,
  106. IMessageLite messageDefaultInstance, IEnumLiteMap enumTypeMap, int number, FieldType type, bool isPacked) :
  107. base(fullName, containingTypeDefaultInstance, new List<TExtensionType>(), messageDefaultInstance, enumTypeMap, number, type, isPacked) {
  108. }
  109. public override object ToReflectionType(object value) {
  110. IList<object> result = new List<object>();
  111. foreach (object element in (IEnumerable) value) {
  112. result.Add(SingularToReflectionType(element));
  113. }
  114. return result;
  115. }
  116. public override object FromReflectionType(object value) {
  117. // Must convert the whole list.
  118. List<TExtensionType> result = new List<TExtensionType>();
  119. foreach (object element in (IEnumerable)value) {
  120. result.Add((TExtensionType)SingularFromReflectionType(element));
  121. }
  122. return result;
  123. }
  124. }
  125. public class GeneratedExtensionLite<TContainingType, TExtensionType> : IGeneratedExtensionLite
  126. where TContainingType : IMessageLite {
  127. private readonly TContainingType containingTypeDefaultInstance;
  128. private readonly TExtensionType defaultValue;
  129. private readonly IMessageLite messageDefaultInstance;
  130. private readonly ExtensionDescriptorLite descriptor;
  131. // We can't always initialize a GeneratedExtension when we first construct
  132. // it due to initialization order difficulties (namely, the default
  133. // instances may not have been constructed yet). So, we construct an
  134. // uninitialized GeneratedExtension once, then call internalInit() on it
  135. // later. Generated code will always call internalInit() on all extensions
  136. // as part of the static initialization code, and internalInit() throws an
  137. // exception if called more than once, so this method is useless to users.
  138. protected GeneratedExtensionLite(
  139. TContainingType containingTypeDefaultInstance,
  140. TExtensionType defaultValue,
  141. IMessageLite messageDefaultInstance,
  142. ExtensionDescriptorLite descriptor) {
  143. this.containingTypeDefaultInstance = containingTypeDefaultInstance;
  144. this.messageDefaultInstance = messageDefaultInstance;
  145. this.defaultValue = defaultValue;
  146. this.descriptor = descriptor;
  147. }
  148. /** For use by generated code only. */
  149. public GeneratedExtensionLite(
  150. string fullName,
  151. TContainingType containingTypeDefaultInstance,
  152. TExtensionType defaultValue,
  153. IMessageLite messageDefaultInstance,
  154. IEnumLiteMap enumTypeMap,
  155. int number,
  156. FieldType type)
  157. : this(containingTypeDefaultInstance, defaultValue, messageDefaultInstance,
  158. new ExtensionDescriptorLite(fullName, enumTypeMap, number, type, defaultValue,
  159. false /* isRepeated */, false /* isPacked */)) {
  160. }
  161. private static readonly IList<object> Empty = new object[0];
  162. /** Repeating fields: For use by generated code only. */
  163. protected GeneratedExtensionLite(
  164. string fullName,
  165. TContainingType containingTypeDefaultInstance,
  166. TExtensionType defaultValue,
  167. IMessageLite messageDefaultInstance,
  168. IEnumLiteMap enumTypeMap,
  169. int number,
  170. FieldType type,
  171. bool isPacked)
  172. : this(containingTypeDefaultInstance, defaultValue, messageDefaultInstance,
  173. new ExtensionDescriptorLite(fullName, enumTypeMap, number, type, Empty,
  174. true /* isRepeated */, isPacked)) {
  175. }
  176. /// <summary>
  177. /// Returns information about this extension
  178. /// </summary>
  179. public IFieldDescriptorLite Descriptor {
  180. get { return descriptor; }
  181. }
  182. /// <summary>
  183. /// Returns the default value for this extension
  184. /// </summary>
  185. public TExtensionType DefaultValue {
  186. get { return defaultValue; }
  187. }
  188. /// <summary>
  189. /// used for the extension registry
  190. /// </summary>
  191. object IGeneratedExtensionLite.ContainingType {
  192. get { return ContainingTypeDefaultInstance; }
  193. }
  194. /**
  195. * Default instance of the type being extended, used to identify that type.
  196. */
  197. public TContainingType ContainingTypeDefaultInstance {
  198. get {
  199. return containingTypeDefaultInstance;
  200. }
  201. }
  202. /** Get the field number. */
  203. public int Number {
  204. get {
  205. return descriptor.FieldNumber;
  206. }
  207. }
  208. /**
  209. * If the extension is an embedded message, this is the default instance of
  210. * that type.
  211. */
  212. public IMessageLite MessageDefaultInstance {
  213. get {
  214. return messageDefaultInstance;
  215. }
  216. }
  217. /// <summary>
  218. /// Converts from the type used by the native accessors to the type
  219. /// used by reflection accessors. For example, the reflection accessors
  220. /// for enums use EnumValueDescriptors but the native accessors use
  221. /// the generated enum type.
  222. /// </summary>
  223. public virtual object ToReflectionType(object value) {
  224. return SingularToReflectionType(value);
  225. }
  226. /// <summary>
  227. /// Like ToReflectionType(object) but for a single element.
  228. /// </summary>
  229. public object SingularToReflectionType(object value) {
  230. return descriptor.MappedType == MappedType.Enum
  231. ? descriptor.EnumType.FindValueByNumber((int)value)
  232. : value;
  233. }
  234. public virtual object FromReflectionType(object value) {
  235. return SingularFromReflectionType(value);
  236. }
  237. public object SingularFromReflectionType(object value) {
  238. switch (Descriptor.MappedType) {
  239. case MappedType.Message:
  240. if (value is TExtensionType) {
  241. return value;
  242. } else {
  243. // It seems the copy of the embedded message stored inside the
  244. // extended message is not of the exact type the user was
  245. // expecting. This can happen if a user defines a
  246. // GeneratedExtension manually and gives it a different type.
  247. // This should not happen in normal use. But, to be nice, we'll
  248. // copy the message to whatever type the caller was expecting.
  249. return MessageDefaultInstance.WeakCreateBuilderForType()
  250. .WeakMergeFrom((IMessageLite)value).WeakBuild();
  251. }
  252. case MappedType.Enum:
  253. // Just return a boxed int - that can be unboxed to the enum
  254. IEnumLite enumValue = (IEnumLite)value;
  255. return enumValue.Number;
  256. default:
  257. return value;
  258. }
  259. }
  260. }
  261. }