DynamicMessage.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  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.Generic;
  36. using System.IO;
  37. using Google.ProtocolBuffers.Descriptors;
  38. namespace Google.ProtocolBuffers
  39. {
  40. /// <summary>
  41. /// An implementation of IMessage that can represent arbitrary types, given a MessageaDescriptor.
  42. /// </summary>
  43. public sealed partial class DynamicMessage : AbstractMessage<DynamicMessage, DynamicMessage.Builder>
  44. {
  45. private readonly MessageDescriptor type;
  46. private readonly FieldSet fields;
  47. private readonly UnknownFieldSet unknownFields;
  48. private int memoizedSize = -1;
  49. /// <summary>
  50. /// Creates a DynamicMessage with the given FieldSet.
  51. /// </summary>
  52. /// <param name="type"></param>
  53. /// <param name="fields"></param>
  54. /// <param name="unknownFields"></param>
  55. private DynamicMessage(MessageDescriptor type, FieldSet fields, UnknownFieldSet unknownFields)
  56. {
  57. this.type = type;
  58. this.fields = fields;
  59. this.unknownFields = unknownFields;
  60. }
  61. /// <summary>
  62. /// Returns a DynamicMessage representing the default instance of the given type.
  63. /// </summary>
  64. /// <param name="type"></param>
  65. /// <returns></returns>
  66. public static DynamicMessage GetDefaultInstance(MessageDescriptor type)
  67. {
  68. return new DynamicMessage(type, FieldSet.DefaultInstance, UnknownFieldSet.DefaultInstance);
  69. }
  70. /// <summary>
  71. /// Parses a message of the given type from the given stream.
  72. /// </summary>
  73. public static DynamicMessage ParseFrom(MessageDescriptor type, ICodedInputStream input)
  74. {
  75. Builder builder = CreateBuilder(type);
  76. Builder dynamicBuilder = builder.MergeFrom(input);
  77. return dynamicBuilder.BuildParsed();
  78. }
  79. /// <summary>
  80. /// Parse a message of the given type from the given stream and extension registry.
  81. /// </summary>
  82. /// <param name="type"></param>
  83. /// <param name="input"></param>
  84. /// <param name="extensionRegistry"></param>
  85. /// <returns></returns>
  86. public static DynamicMessage ParseFrom(MessageDescriptor type, ICodedInputStream input,
  87. ExtensionRegistry extensionRegistry)
  88. {
  89. Builder builder = CreateBuilder(type);
  90. Builder dynamicBuilder = builder.MergeFrom(input, extensionRegistry);
  91. return dynamicBuilder.BuildParsed();
  92. }
  93. /// <summary>
  94. /// Parses a message of the given type from the given stream.
  95. /// </summary>
  96. public static DynamicMessage ParseFrom(MessageDescriptor type, Stream input)
  97. {
  98. Builder builder = CreateBuilder(type);
  99. Builder dynamicBuilder = builder.MergeFrom(input);
  100. return dynamicBuilder.BuildParsed();
  101. }
  102. /// <summary>
  103. /// Parse a message of the given type from the given stream and extension registry.
  104. /// </summary>
  105. /// <param name="type"></param>
  106. /// <param name="input"></param>
  107. /// <param name="extensionRegistry"></param>
  108. /// <returns></returns>
  109. public static DynamicMessage ParseFrom(MessageDescriptor type, Stream input, ExtensionRegistry extensionRegistry)
  110. {
  111. Builder builder = CreateBuilder(type);
  112. Builder dynamicBuilder = builder.MergeFrom(input, extensionRegistry);
  113. return dynamicBuilder.BuildParsed();
  114. }
  115. /// <summary>
  116. /// Parse <paramref name="data"/> as a message of the given type and return it.
  117. /// </summary>
  118. public static DynamicMessage ParseFrom(MessageDescriptor type, ByteString data)
  119. {
  120. Builder builder = CreateBuilder(type);
  121. Builder dynamicBuilder = builder.MergeFrom(data);
  122. return dynamicBuilder.BuildParsed();
  123. }
  124. /// <summary>
  125. /// Parse <paramref name="data"/> as a message of the given type and return it.
  126. /// </summary>
  127. public static DynamicMessage ParseFrom(MessageDescriptor type, ByteString data,
  128. ExtensionRegistry extensionRegistry)
  129. {
  130. Builder builder = CreateBuilder(type);
  131. Builder dynamicBuilder = builder.MergeFrom(data, extensionRegistry);
  132. return dynamicBuilder.BuildParsed();
  133. }
  134. /// <summary>
  135. /// Parse <paramref name="data"/> as a message of the given type and return it.
  136. /// </summary>
  137. public static DynamicMessage ParseFrom(MessageDescriptor type, byte[] data)
  138. {
  139. Builder builder = CreateBuilder(type);
  140. Builder dynamicBuilder = builder.MergeFrom(data);
  141. return dynamicBuilder.BuildParsed();
  142. }
  143. /// <summary>
  144. /// Parse <paramref name="data"/> as a message of the given type and return it.
  145. /// </summary>
  146. public static DynamicMessage ParseFrom(MessageDescriptor type, byte[] data, ExtensionRegistry extensionRegistry)
  147. {
  148. Builder builder = CreateBuilder(type);
  149. Builder dynamicBuilder = builder.MergeFrom(data, extensionRegistry);
  150. return dynamicBuilder.BuildParsed();
  151. }
  152. /// <summary>
  153. /// Constructs a builder for the given type.
  154. /// </summary>
  155. public static Builder CreateBuilder(MessageDescriptor type)
  156. {
  157. return new Builder(type);
  158. }
  159. /// <summary>
  160. /// Constructs a builder for a message of the same type as <paramref name="prototype"/>,
  161. /// and initializes it with the same contents.
  162. /// </summary>
  163. /// <param name="prototype"></param>
  164. /// <returns></returns>
  165. public static Builder CreateBuilder(IMessage prototype)
  166. {
  167. return new Builder(prototype.DescriptorForType).MergeFrom(prototype);
  168. }
  169. // -----------------------------------------------------------------
  170. // Implementation of IMessage interface.
  171. public override MessageDescriptor DescriptorForType
  172. {
  173. get { return type; }
  174. }
  175. public override DynamicMessage DefaultInstanceForType
  176. {
  177. get { return GetDefaultInstance(type); }
  178. }
  179. public override IDictionary<FieldDescriptor, object> AllFields
  180. {
  181. get { return fields.AllFieldDescriptors; }
  182. }
  183. public override bool HasField(FieldDescriptor field)
  184. {
  185. VerifyContainingType(field);
  186. return fields.HasField(field);
  187. }
  188. public override object this[FieldDescriptor field]
  189. {
  190. get
  191. {
  192. VerifyContainingType(field);
  193. object result = fields[field];
  194. if (result == null)
  195. {
  196. result = GetDefaultInstance(field.MessageType);
  197. }
  198. return result;
  199. }
  200. }
  201. public override int GetRepeatedFieldCount(FieldDescriptor field)
  202. {
  203. VerifyContainingType(field);
  204. return fields.GetRepeatedFieldCount(field);
  205. }
  206. public override object this[FieldDescriptor field, int index]
  207. {
  208. get
  209. {
  210. VerifyContainingType(field);
  211. return fields[field, index];
  212. }
  213. }
  214. public override UnknownFieldSet UnknownFields
  215. {
  216. get { return unknownFields; }
  217. }
  218. public bool Initialized
  219. {
  220. get { return fields.IsInitializedWithRespectTo(type.Fields); }
  221. }
  222. public override void WriteTo(ICodedOutputStream output)
  223. {
  224. fields.WriteTo(output);
  225. if (type.Options.MessageSetWireFormat)
  226. {
  227. unknownFields.WriteAsMessageSetTo(output);
  228. }
  229. else
  230. {
  231. unknownFields.WriteTo(output);
  232. }
  233. }
  234. public override int SerializedSize
  235. {
  236. get
  237. {
  238. int size = memoizedSize;
  239. if (size != -1)
  240. {
  241. return size;
  242. }
  243. size = fields.SerializedSize;
  244. if (type.Options.MessageSetWireFormat)
  245. {
  246. size += unknownFields.SerializedSizeAsMessageSet;
  247. }
  248. else
  249. {
  250. size += unknownFields.SerializedSize;
  251. }
  252. memoizedSize = size;
  253. return size;
  254. }
  255. }
  256. public override Builder CreateBuilderForType()
  257. {
  258. return new Builder(type);
  259. }
  260. public override Builder ToBuilder()
  261. {
  262. return CreateBuilderForType().MergeFrom(this);
  263. }
  264. /// <summary>
  265. /// Verifies that the field is a field of this message.
  266. /// </summary>
  267. private void VerifyContainingType(FieldDescriptor field)
  268. {
  269. if (field.ContainingType != type)
  270. {
  271. throw new ArgumentException("FieldDescriptor does not match message type.");
  272. }
  273. }
  274. /// <summary>
  275. /// Builder for dynamic messages. Instances are created with DynamicMessage.CreateBuilder.
  276. /// </summary>
  277. public sealed partial class Builder : AbstractBuilder<DynamicMessage, Builder>
  278. {
  279. private readonly MessageDescriptor type;
  280. private FieldSet fields;
  281. private UnknownFieldSet unknownFields;
  282. internal Builder(MessageDescriptor type)
  283. {
  284. this.type = type;
  285. this.fields = FieldSet.CreateInstance();
  286. this.unknownFields = UnknownFieldSet.DefaultInstance;
  287. }
  288. protected override Builder ThisBuilder
  289. {
  290. get { return this; }
  291. }
  292. public override Builder Clear()
  293. {
  294. fields.Clear();
  295. return this;
  296. }
  297. public override Builder MergeFrom(IMessage other)
  298. {
  299. if (other.DescriptorForType != type)
  300. {
  301. throw new ArgumentException("MergeFrom(IMessage) can only merge messages of the same type.");
  302. }
  303. fields.MergeFrom(other);
  304. MergeUnknownFields(other.UnknownFields);
  305. return this;
  306. }
  307. public override Builder MergeFrom(DynamicMessage other)
  308. {
  309. IMessage downcast = other;
  310. return MergeFrom(downcast);
  311. }
  312. public override DynamicMessage Build()
  313. {
  314. if (fields != null && !IsInitialized)
  315. {
  316. throw new UninitializedMessageException(new DynamicMessage(type, fields, unknownFields));
  317. }
  318. return BuildPartial();
  319. }
  320. /// <summary>
  321. /// Helper for DynamicMessage.ParseFrom() methods to call. Throws
  322. /// InvalidProtocolBufferException
  323. /// </summary>
  324. /// <returns></returns>
  325. internal DynamicMessage BuildParsed()
  326. {
  327. if (!IsInitialized)
  328. {
  329. throw new UninitializedMessageException(new DynamicMessage(type, fields, unknownFields)).
  330. AsInvalidProtocolBufferException();
  331. }
  332. return BuildPartial();
  333. }
  334. public override DynamicMessage BuildPartial()
  335. {
  336. if (fields == null)
  337. {
  338. throw new InvalidOperationException("Build() has already been called on this Builder.");
  339. }
  340. fields.MakeImmutable();
  341. DynamicMessage result = new DynamicMessage(type, fields, unknownFields);
  342. fields = null;
  343. unknownFields = null;
  344. return result;
  345. }
  346. public override Builder Clone()
  347. {
  348. Builder result = new Builder(type);
  349. result.fields.MergeFrom(fields);
  350. return result;
  351. }
  352. public override bool IsInitialized
  353. {
  354. get { return fields.IsInitializedWithRespectTo(type.Fields); }
  355. }
  356. public override Builder MergeFrom(ICodedInputStream input, ExtensionRegistry extensionRegistry)
  357. {
  358. UnknownFieldSet.Builder unknownFieldsBuilder = UnknownFieldSet.CreateBuilder(unknownFields);
  359. unknownFieldsBuilder.MergeFrom(input, extensionRegistry, this);
  360. unknownFields = unknownFieldsBuilder.Build();
  361. return this;
  362. }
  363. public override MessageDescriptor DescriptorForType
  364. {
  365. get { return type; }
  366. }
  367. public override DynamicMessage DefaultInstanceForType
  368. {
  369. get { return GetDefaultInstance(type); }
  370. }
  371. public override IDictionary<FieldDescriptor, object> AllFields
  372. {
  373. get { return fields.AllFieldDescriptors; }
  374. }
  375. public override IBuilder CreateBuilderForField(FieldDescriptor field)
  376. {
  377. VerifyContainingType(field);
  378. if (field.MappedType != MappedType.Message)
  379. {
  380. throw new ArgumentException("CreateBuilderForField is only valid for fields with message type.");
  381. }
  382. return new Builder(field.MessageType);
  383. }
  384. public override bool HasField(FieldDescriptor field)
  385. {
  386. VerifyContainingType(field);
  387. return fields.HasField(field);
  388. }
  389. public override object this[FieldDescriptor field, int index]
  390. {
  391. get
  392. {
  393. VerifyContainingType(field);
  394. return fields[field, index];
  395. }
  396. set
  397. {
  398. VerifyContainingType(field);
  399. fields[field, index] = value;
  400. }
  401. }
  402. public override object this[FieldDescriptor field]
  403. {
  404. get
  405. {
  406. VerifyContainingType(field);
  407. object result = fields[field];
  408. if (result == null)
  409. {
  410. result = GetDefaultInstance(field.MessageType);
  411. }
  412. return result;
  413. }
  414. set
  415. {
  416. VerifyContainingType(field);
  417. fields[field] = value;
  418. }
  419. }
  420. public override Builder ClearField(FieldDescriptor field)
  421. {
  422. VerifyContainingType(field);
  423. fields.ClearField(field);
  424. return this;
  425. }
  426. public override int GetRepeatedFieldCount(FieldDescriptor field)
  427. {
  428. VerifyContainingType(field);
  429. return fields.GetRepeatedFieldCount(field);
  430. }
  431. public override Builder AddRepeatedField(FieldDescriptor field, object value)
  432. {
  433. VerifyContainingType(field);
  434. fields.AddRepeatedField(field, value);
  435. return this;
  436. }
  437. public override UnknownFieldSet UnknownFields
  438. {
  439. get { return unknownFields; }
  440. set { unknownFields = value; }
  441. }
  442. /// <summary>
  443. /// Verifies that the field is a field of this message.
  444. /// </summary>
  445. /// <param name="field"></param>
  446. private void VerifyContainingType(FieldDescriptor field)
  447. {
  448. if (field.ContainingType != type)
  449. {
  450. throw new ArgumentException("FieldDescriptor does not match message type.");
  451. }
  452. }
  453. }
  454. }
  455. }