GeneratedExtensionLite.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  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. {
  41. public interface IGeneratedExtensionLite
  42. {
  43. int Number { get; }
  44. object ContainingType { get; }
  45. IMessageLite MessageDefaultInstance { get; }
  46. IFieldDescriptorLite Descriptor { get; }
  47. }
  48. public class ExtensionDescriptorLite : IFieldDescriptorLite
  49. {
  50. private readonly string fullName;
  51. private readonly IEnumLiteMap enumTypeMap;
  52. private readonly int number;
  53. private readonly FieldType type;
  54. private readonly bool isRepeated;
  55. private readonly bool isPacked;
  56. private readonly MappedType mapType;
  57. private readonly object defaultValue;
  58. public ExtensionDescriptorLite(string fullName, IEnumLiteMap enumTypeMap, int number, FieldType type,
  59. object defaultValue, bool isRepeated, bool isPacked)
  60. {
  61. this.fullName = fullName;
  62. this.enumTypeMap = enumTypeMap;
  63. this.number = number;
  64. this.type = type;
  65. this.mapType = FieldMappingAttribute.MappedTypeFromFieldType(type);
  66. this.isRepeated = isRepeated;
  67. this.isPacked = isPacked;
  68. this.defaultValue = defaultValue;
  69. }
  70. public string Name
  71. {
  72. get
  73. {
  74. string name = fullName;
  75. int offset = name.LastIndexOf('.');
  76. if (offset >= 0)
  77. name = name.Substring(offset);
  78. return name;
  79. }
  80. }
  81. public string FullName
  82. {
  83. get { return fullName; }
  84. }
  85. public bool IsRepeated
  86. {
  87. get { return isRepeated; }
  88. }
  89. public bool IsRequired
  90. {
  91. get { return false; }
  92. }
  93. public bool IsPacked
  94. {
  95. get { return isPacked; }
  96. }
  97. public bool IsExtension
  98. {
  99. get { return true; }
  100. }
  101. /// <summary>
  102. /// This is not supported and assertions are made to ensure this does not exist on extensions of Lite types
  103. /// </summary>
  104. public bool MessageSetWireFormat
  105. {
  106. get { return false; }
  107. }
  108. public int FieldNumber
  109. {
  110. get { return number; }
  111. }
  112. public IEnumLiteMap EnumType
  113. {
  114. get { return enumTypeMap; }
  115. }
  116. public FieldType FieldType
  117. {
  118. get { return type; }
  119. }
  120. public MappedType MappedType
  121. {
  122. get { return mapType; }
  123. }
  124. public object DefaultValue
  125. {
  126. get { return defaultValue; }
  127. }
  128. public int CompareTo(IFieldDescriptorLite other)
  129. {
  130. return FieldNumber.CompareTo(other.FieldNumber);
  131. }
  132. }
  133. public class GeneratedRepeatExtensionLite<TContainingType, TExtensionType> :
  134. GeneratedExtensionLite<TContainingType, IList<TExtensionType>>
  135. where TContainingType : IMessageLite
  136. {
  137. public GeneratedRepeatExtensionLite(string fullName, TContainingType containingTypeDefaultInstance,
  138. IMessageLite messageDefaultInstance, IEnumLiteMap enumTypeMap, int number,
  139. FieldType type, bool isPacked) :
  140. base(
  141. fullName, containingTypeDefaultInstance, new List<TExtensionType>(),
  142. messageDefaultInstance, enumTypeMap, number, type, isPacked)
  143. {
  144. }
  145. public override object ToReflectionType(object value)
  146. {
  147. IList<object> result = new List<object>();
  148. foreach (object element in (IEnumerable) value)
  149. {
  150. result.Add(SingularToReflectionType(element));
  151. }
  152. return result;
  153. }
  154. public override object FromReflectionType(object value)
  155. {
  156. // Must convert the whole list.
  157. List<TExtensionType> result = new List<TExtensionType>();
  158. foreach (object element in (IEnumerable) value)
  159. {
  160. result.Add((TExtensionType) SingularFromReflectionType(element));
  161. }
  162. return result;
  163. }
  164. }
  165. public class GeneratedExtensionLite<TContainingType, TExtensionType> : IGeneratedExtensionLite
  166. where TContainingType : IMessageLite
  167. {
  168. private readonly TContainingType containingTypeDefaultInstance;
  169. private readonly TExtensionType defaultValue;
  170. private readonly IMessageLite messageDefaultInstance;
  171. private readonly ExtensionDescriptorLite descriptor;
  172. // We can't always initialize a GeneratedExtension when we first construct
  173. // it due to initialization order difficulties (namely, the default
  174. // instances may not have been constructed yet). So, we construct an
  175. // uninitialized GeneratedExtension once, then call internalInit() on it
  176. // later. Generated code will always call internalInit() on all extensions
  177. // as part of the static initialization code, and internalInit() throws an
  178. // exception if called more than once, so this method is useless to users.
  179. protected GeneratedExtensionLite(
  180. TContainingType containingTypeDefaultInstance,
  181. TExtensionType defaultValue,
  182. IMessageLite messageDefaultInstance,
  183. ExtensionDescriptorLite descriptor)
  184. {
  185. this.containingTypeDefaultInstance = containingTypeDefaultInstance;
  186. this.messageDefaultInstance = messageDefaultInstance;
  187. this.defaultValue = defaultValue;
  188. this.descriptor = descriptor;
  189. }
  190. /** For use by generated code only. */
  191. public GeneratedExtensionLite(
  192. string fullName,
  193. TContainingType containingTypeDefaultInstance,
  194. TExtensionType defaultValue,
  195. IMessageLite messageDefaultInstance,
  196. IEnumLiteMap enumTypeMap,
  197. int number,
  198. FieldType type)
  199. : this(containingTypeDefaultInstance, defaultValue, messageDefaultInstance,
  200. new ExtensionDescriptorLite(fullName, enumTypeMap, number, type, defaultValue,
  201. false /* isRepeated */, false /* isPacked */))
  202. {
  203. }
  204. private static readonly IList<object> Empty = new object[0];
  205. /** Repeating fields: For use by generated code only. */
  206. protected GeneratedExtensionLite(
  207. string fullName,
  208. TContainingType containingTypeDefaultInstance,
  209. TExtensionType defaultValue,
  210. IMessageLite messageDefaultInstance,
  211. IEnumLiteMap enumTypeMap,
  212. int number,
  213. FieldType type,
  214. bool isPacked)
  215. : this(containingTypeDefaultInstance, defaultValue, messageDefaultInstance,
  216. new ExtensionDescriptorLite(fullName, enumTypeMap, number, type, Empty,
  217. true /* isRepeated */, isPacked))
  218. {
  219. }
  220. /// <summary>
  221. /// Returns information about this extension
  222. /// </summary>
  223. public IFieldDescriptorLite Descriptor
  224. {
  225. get { return descriptor; }
  226. }
  227. /// <summary>
  228. /// Returns the default value for this extension
  229. /// </summary>
  230. public TExtensionType DefaultValue
  231. {
  232. get { return defaultValue; }
  233. }
  234. /// <summary>
  235. /// used for the extension registry
  236. /// </summary>
  237. object IGeneratedExtensionLite.ContainingType
  238. {
  239. get { return ContainingTypeDefaultInstance; }
  240. }
  241. /**
  242. * Default instance of the type being extended, used to identify that type.
  243. */
  244. public TContainingType ContainingTypeDefaultInstance
  245. {
  246. get { return containingTypeDefaultInstance; }
  247. }
  248. /** Get the field number. */
  249. public int Number
  250. {
  251. get { return descriptor.FieldNumber; }
  252. }
  253. /**
  254. * If the extension is an embedded message, this is the default instance of
  255. * that type.
  256. */
  257. public IMessageLite MessageDefaultInstance
  258. {
  259. get { return messageDefaultInstance; }
  260. }
  261. /// <summary>
  262. /// Converts from the type used by the native accessors to the type
  263. /// used by reflection accessors. For example, the reflection accessors
  264. /// for enums use EnumValueDescriptors but the native accessors use
  265. /// the generated enum type.
  266. /// </summary>
  267. public virtual object ToReflectionType(object value)
  268. {
  269. return SingularToReflectionType(value);
  270. }
  271. /// <summary>
  272. /// Like ToReflectionType(object) but for a single element.
  273. /// </summary>
  274. public object SingularToReflectionType(object value)
  275. {
  276. return descriptor.MappedType == MappedType.Enum
  277. ? descriptor.EnumType.FindValueByNumber((int) value)
  278. : value;
  279. }
  280. public virtual object FromReflectionType(object value)
  281. {
  282. return SingularFromReflectionType(value);
  283. }
  284. public object SingularFromReflectionType(object value)
  285. {
  286. switch (Descriptor.MappedType)
  287. {
  288. case MappedType.Message:
  289. if (value is TExtensionType)
  290. {
  291. return value;
  292. }
  293. else
  294. {
  295. // It seems the copy of the embedded message stored inside the
  296. // extended message is not of the exact type the user was
  297. // expecting. This can happen if a user defines a
  298. // GeneratedExtension manually and gives it a different type.
  299. // This should not happen in normal use. But, to be nice, we'll
  300. // copy the message to whatever type the caller was expecting.
  301. return MessageDefaultInstance.WeakCreateBuilderForType()
  302. .WeakMergeFrom((IMessageLite) value).WeakBuild();
  303. }
  304. case MappedType.Enum:
  305. // Just return a boxed int - that can be unboxed to the enum
  306. IEnumLite enumValue = (IEnumLite) value;
  307. return enumValue.Number;
  308. default:
  309. return value;
  310. }
  311. }
  312. }
  313. }