AbstractReader.cs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701
  1. using System;
  2. using System.Collections.Generic;
  3. using Google.ProtocolBuffers.Descriptors;
  4. //Disable CS3011: only CLS-compliant members can be abstract
  5. #pragma warning disable 3011
  6. namespace Google.ProtocolBuffers.Serialization
  7. {
  8. /// <summary>
  9. /// Provides a base-class that provides some basic functionality for handling type dispatching
  10. /// </summary>
  11. public abstract class AbstractReader : ICodedInputStream
  12. {
  13. private const int DefaultMaxDepth = 64;
  14. private int _depth;
  15. /// <summary> Constructs a new reader </summary>
  16. protected AbstractReader() { MaxDepth = DefaultMaxDepth; }
  17. /// <summary> Gets or sets the maximum recursion depth allowed </summary>
  18. public int MaxDepth { get; set; }
  19. /// <summary>
  20. /// Merges the contents of stream into the provided message builder
  21. /// </summary>
  22. public TBuilder Merge<TBuilder>(TBuilder builder) where TBuilder : IBuilderLite
  23. {
  24. return Merge(builder, ExtensionRegistry.Empty);
  25. }
  26. /// <summary>
  27. /// Merges the contents of stream into the provided message builder
  28. /// </summary>
  29. public abstract TBuilder Merge<TBuilder>(TBuilder builder, ExtensionRegistry registry)
  30. where TBuilder : IBuilderLite;
  31. /// <summary>
  32. /// Peeks at the next field in the input stream and returns what information is available.
  33. /// </summary>
  34. /// <remarks>
  35. /// This may be called multiple times without actually reading the field. Only after the field
  36. /// is either read, or skipped, should PeekNext return a different value.
  37. /// </remarks>
  38. protected abstract bool PeekNext(out string field);
  39. /// <summary>
  40. /// Causes the reader to skip past this field
  41. /// </summary>
  42. protected abstract void Skip();
  43. /// <summary>
  44. /// Returns true if it was able to read a Boolean from the input
  45. /// </summary>
  46. protected abstract bool Read(ref bool value);
  47. /// <summary>
  48. /// Returns true if it was able to read a Int32 from the input
  49. /// </summary>
  50. protected abstract bool Read(ref int value);
  51. /// <summary>
  52. /// Returns true if it was able to read a UInt32 from the input
  53. /// </summary>
  54. [CLSCompliant(false)]
  55. protected abstract bool Read(ref uint value);
  56. /// <summary>
  57. /// Returns true if it was able to read a Int64 from the input
  58. /// </summary>
  59. protected abstract bool Read(ref long value);
  60. /// <summary>
  61. /// Returns true if it was able to read a UInt64 from the input
  62. /// </summary>
  63. [CLSCompliant(false)]
  64. protected abstract bool Read(ref ulong value);
  65. /// <summary>
  66. /// Returns true if it was able to read a Single from the input
  67. /// </summary>
  68. protected abstract bool Read(ref float value);
  69. /// <summary>
  70. /// Returns true if it was able to read a Double from the input
  71. /// </summary>
  72. protected abstract bool Read(ref double value);
  73. /// <summary>
  74. /// Returns true if it was able to read a String from the input
  75. /// </summary>
  76. protected abstract bool Read(ref string value);
  77. /// <summary>
  78. /// Returns true if it was able to read a ByteString from the input
  79. /// </summary>
  80. protected abstract bool Read(ref ByteString value);
  81. /// <summary>
  82. /// returns true if it was able to read a single value into the value reference. The value
  83. /// stored may be of type System.String, System.Int32, or an IEnumLite from the IEnumLiteMap.
  84. /// </summary>
  85. protected abstract bool ReadEnum(ref object value);
  86. /// <summary>
  87. /// Merges the input stream into the provided IBuilderLite
  88. /// </summary>
  89. protected abstract bool ReadMessage(IBuilderLite builder, ExtensionRegistry registry);
  90. /// <summary>
  91. /// Reads the root-message preamble specific to this formatter
  92. /// </summary>
  93. public abstract void ReadMessageStart();
  94. /// <summary>
  95. /// Reads the root-message close specific to this formatter
  96. /// </summary>
  97. public abstract void ReadMessageEnd();
  98. /// <summary>
  99. /// Merges the input stream into the provided IBuilderLite
  100. /// </summary>
  101. public virtual bool ReadGroup(IBuilderLite value, ExtensionRegistry registry)
  102. {
  103. return ReadMessage(value, registry);
  104. }
  105. /// <summary>
  106. /// Cursors through the array elements and stops at the end of the array
  107. /// </summary>
  108. protected virtual IEnumerable<string> ForeachArrayItem(string field)
  109. {
  110. string next = field;
  111. while (true)
  112. {
  113. yield return next;
  114. if (!PeekNext(out next) || next != field)
  115. {
  116. break;
  117. }
  118. }
  119. }
  120. /// <summary>
  121. /// Reads an array of T messages
  122. /// </summary>
  123. public virtual bool ReadMessageArray<T>(string field, ICollection<T> items, IMessageLite messageType,
  124. ExtensionRegistry registry)
  125. {
  126. bool success = false;
  127. foreach (string next in ForeachArrayItem(field))
  128. {
  129. IBuilderLite builder = messageType.WeakCreateBuilderForType();
  130. if (ReadMessage(builder, registry))
  131. {
  132. items.Add((T) builder.WeakBuild());
  133. success |= true;
  134. }
  135. }
  136. return success;
  137. }
  138. /// <summary>
  139. /// Reads an array of T messages as a proto-buffer group
  140. /// </summary>
  141. public virtual bool ReadGroupArray<T>(string field, ICollection<T> items, IMessageLite messageType,
  142. ExtensionRegistry registry)
  143. {
  144. bool success = false;
  145. foreach (string next in ForeachArrayItem(field))
  146. {
  147. IBuilderLite builder = messageType.WeakCreateBuilderForType();
  148. if (ReadGroup(builder, registry))
  149. {
  150. items.Add((T) builder.WeakBuild());
  151. success |= true;
  152. }
  153. }
  154. return success;
  155. }
  156. /// <summary>
  157. /// Reads an array of System.Enum type T and adds them to the collection
  158. /// </summary>
  159. public virtual bool ReadEnumArray(string field, ICollection<object> items)
  160. {
  161. bool success = false;
  162. foreach (string next in ForeachArrayItem(field))
  163. {
  164. object temp = null;
  165. if (ReadEnum(ref temp))
  166. {
  167. items.Add(temp);
  168. success |= true;
  169. }
  170. }
  171. return success;
  172. }
  173. /// <summary>
  174. /// Reads an array of T, where T is a primitive type defined by FieldType
  175. /// </summary>
  176. public virtual bool ReadArray<T>(FieldType type, string field, ICollection<T> items)
  177. {
  178. bool success = false;
  179. foreach (string next in ForeachArrayItem(field))
  180. {
  181. object temp = null;
  182. if (ReadField(type, ref temp))
  183. {
  184. items.Add((T) temp);
  185. success |= true;
  186. }
  187. }
  188. return success;
  189. }
  190. /// <summary>
  191. /// returns true if it was able to read a single primitive value of FieldType into the value reference
  192. /// </summary>
  193. public virtual bool ReadField(FieldType type, ref object value)
  194. {
  195. switch (type)
  196. {
  197. case FieldType.Bool:
  198. {
  199. bool temp = false;
  200. if (Read(ref temp))
  201. {
  202. value = temp;
  203. }
  204. else
  205. {
  206. return false;
  207. }
  208. break;
  209. }
  210. case FieldType.Int64:
  211. case FieldType.SInt64:
  212. case FieldType.SFixed64:
  213. {
  214. long temp = 0;
  215. if (Read(ref temp))
  216. {
  217. value = temp;
  218. }
  219. else
  220. {
  221. return false;
  222. }
  223. break;
  224. }
  225. case FieldType.UInt64:
  226. case FieldType.Fixed64:
  227. {
  228. ulong temp = 0;
  229. if (Read(ref temp))
  230. {
  231. value = temp;
  232. }
  233. else
  234. {
  235. return false;
  236. }
  237. break;
  238. }
  239. case FieldType.Int32:
  240. case FieldType.SInt32:
  241. case FieldType.SFixed32:
  242. {
  243. int temp = 0;
  244. if (Read(ref temp))
  245. {
  246. value = temp;
  247. }
  248. else
  249. {
  250. return false;
  251. }
  252. break;
  253. }
  254. case FieldType.UInt32:
  255. case FieldType.Fixed32:
  256. {
  257. uint temp = 0;
  258. if (Read(ref temp))
  259. {
  260. value = temp;
  261. }
  262. else
  263. {
  264. return false;
  265. }
  266. break;
  267. }
  268. case FieldType.Float:
  269. {
  270. float temp = float.NaN;
  271. if (Read(ref temp))
  272. {
  273. value = temp;
  274. }
  275. else
  276. {
  277. return false;
  278. }
  279. break;
  280. }
  281. case FieldType.Double:
  282. {
  283. double temp = float.NaN;
  284. if (Read(ref temp))
  285. {
  286. value = temp;
  287. }
  288. else
  289. {
  290. return false;
  291. }
  292. break;
  293. }
  294. case FieldType.String:
  295. {
  296. string temp = null;
  297. if (Read(ref temp))
  298. {
  299. value = temp;
  300. }
  301. else
  302. {
  303. return false;
  304. }
  305. break;
  306. }
  307. case FieldType.Bytes:
  308. {
  309. ByteString temp = null;
  310. if (Read(ref temp))
  311. {
  312. value = temp;
  313. }
  314. else
  315. {
  316. return false;
  317. }
  318. break;
  319. }
  320. default:
  321. throw InvalidProtocolBufferException.InvalidTag();
  322. }
  323. return true;
  324. }
  325. #region ICodedInputStream Members
  326. bool ICodedInputStream.ReadTag(out uint fieldTag, out string fieldName)
  327. {
  328. fieldTag = 0;
  329. if (PeekNext(out fieldName))
  330. {
  331. return true;
  332. }
  333. return false;
  334. }
  335. bool ICodedInputStream.ReadDouble(ref double value)
  336. {
  337. return Read(ref value);
  338. }
  339. bool ICodedInputStream.ReadFloat(ref float value)
  340. {
  341. return Read(ref value);
  342. }
  343. bool ICodedInputStream.ReadUInt64(ref ulong value)
  344. {
  345. return Read(ref value);
  346. }
  347. bool ICodedInputStream.ReadInt64(ref long value)
  348. {
  349. return Read(ref value);
  350. }
  351. bool ICodedInputStream.ReadInt32(ref int value)
  352. {
  353. return Read(ref value);
  354. }
  355. bool ICodedInputStream.ReadFixed64(ref ulong value)
  356. {
  357. return Read(ref value);
  358. }
  359. bool ICodedInputStream.ReadFixed32(ref uint value)
  360. {
  361. return Read(ref value);
  362. }
  363. bool ICodedInputStream.ReadBool(ref bool value)
  364. {
  365. return Read(ref value);
  366. }
  367. bool ICodedInputStream.ReadString(ref string value)
  368. {
  369. return Read(ref value);
  370. }
  371. void ICodedInputStream.ReadGroup(int fieldNumber, IBuilderLite builder, ExtensionRegistry extensionRegistry)
  372. {
  373. if (_depth++ > MaxDepth)
  374. {
  375. throw new RecursionLimitExceededException();
  376. }
  377. ReadGroup(builder, extensionRegistry);
  378. _depth--;
  379. }
  380. void ICodedInputStream.ReadUnknownGroup(int fieldNumber, IBuilderLite builder)
  381. {
  382. throw new NotSupportedException();
  383. }
  384. void ICodedInputStream.ReadMessage(IBuilderLite builder, ExtensionRegistry extensionRegistry)
  385. {
  386. if (_depth++ > MaxDepth)
  387. {
  388. throw new RecursionLimitExceededException();
  389. }
  390. ReadMessage(builder, extensionRegistry);
  391. _depth--;
  392. }
  393. bool ICodedInputStream.ReadBytes(ref ByteString value)
  394. {
  395. return Read(ref value);
  396. }
  397. bool ICodedInputStream.ReadUInt32(ref uint value)
  398. {
  399. return Read(ref value);
  400. }
  401. bool ICodedInputStream.ReadEnum(ref IEnumLite value, out object unknown, IEnumLiteMap mapping)
  402. {
  403. value = null;
  404. unknown = null;
  405. if (ReadEnum(ref unknown))
  406. {
  407. if (unknown is int)
  408. {
  409. value = mapping.FindValueByNumber((int) unknown);
  410. }
  411. else if (unknown is string)
  412. {
  413. value = mapping.FindValueByName((string) unknown);
  414. }
  415. return value != null;
  416. }
  417. return false;
  418. }
  419. bool ICodedInputStream.ReadEnum<T>(ref T value, out object rawValue)
  420. {
  421. rawValue = null;
  422. if (ReadEnum(ref rawValue))
  423. {
  424. if (Enum.IsDefined(typeof (T), rawValue))
  425. {
  426. if (rawValue is int)
  427. {
  428. value = (T) rawValue;
  429. }
  430. else if (rawValue is string)
  431. {
  432. value = (T) Enum.Parse(typeof (T), (string) rawValue, false);
  433. }
  434. else
  435. {
  436. value = default(T);
  437. return false;
  438. }
  439. return true;
  440. }
  441. }
  442. return false;
  443. }
  444. bool ICodedInputStream.ReadSFixed32(ref int value)
  445. {
  446. return Read(ref value);
  447. }
  448. bool ICodedInputStream.ReadSFixed64(ref long value)
  449. {
  450. return Read(ref value);
  451. }
  452. bool ICodedInputStream.ReadSInt32(ref int value)
  453. {
  454. return Read(ref value);
  455. }
  456. bool ICodedInputStream.ReadSInt64(ref long value)
  457. {
  458. return Read(ref value);
  459. }
  460. void ICodedInputStream.ReadPrimitiveArray(FieldType fieldType, uint fieldTag, string fieldName,
  461. ICollection<object> list)
  462. {
  463. ReadArray(fieldType, fieldName, list);
  464. }
  465. void ICodedInputStream.ReadEnumArray(uint fieldTag, string fieldName, ICollection<IEnumLite> list,
  466. out ICollection<object> unknown, IEnumLiteMap mapping)
  467. {
  468. unknown = null;
  469. List<object> array = new List<object>();
  470. if (ReadEnumArray(fieldName, array))
  471. {
  472. foreach (object rawValue in array)
  473. {
  474. IEnumLite item = null;
  475. if (rawValue is int)
  476. {
  477. item = mapping.FindValueByNumber((int) rawValue);
  478. }
  479. else if (rawValue is string)
  480. {
  481. item = mapping.FindValueByName((string) rawValue);
  482. }
  483. if (item != null)
  484. {
  485. list.Add(item);
  486. }
  487. else
  488. {
  489. if (unknown == null)
  490. {
  491. unknown = new List<object>();
  492. }
  493. unknown.Add(rawValue);
  494. }
  495. }
  496. }
  497. }
  498. void ICodedInputStream.ReadEnumArray<T>(uint fieldTag, string fieldName, ICollection<T> list,
  499. out ICollection<object> unknown)
  500. {
  501. unknown = null;
  502. List<object> array = new List<object>();
  503. if (ReadEnumArray(fieldName, array))
  504. {
  505. foreach (object rawValue in array)
  506. {
  507. if (rawValue is int)
  508. {
  509. list.Add((T) rawValue);
  510. }
  511. else if (rawValue is string)
  512. {
  513. list.Add((T) Enum.Parse(typeof (T), (string) rawValue, false));
  514. }
  515. else
  516. {
  517. if (unknown == null)
  518. {
  519. unknown = new List<object>();
  520. }
  521. unknown.Add(rawValue);
  522. }
  523. }
  524. }
  525. }
  526. void ICodedInputStream.ReadMessageArray<T>(uint fieldTag, string fieldName, ICollection<T> list, T messageType,
  527. ExtensionRegistry registry)
  528. {
  529. if (_depth++ > MaxDepth)
  530. {
  531. throw new RecursionLimitExceededException();
  532. }
  533. ReadMessageArray(fieldName, list, messageType, registry);
  534. _depth--;
  535. }
  536. void ICodedInputStream.ReadGroupArray<T>(uint fieldTag, string fieldName, ICollection<T> list, T messageType,
  537. ExtensionRegistry registry)
  538. {
  539. if (_depth++ > MaxDepth)
  540. {
  541. throw new RecursionLimitExceededException();
  542. }
  543. ReadGroupArray(fieldName, list, messageType, registry);
  544. _depth--;
  545. }
  546. bool ICodedInputStream.ReadPrimitiveField(FieldType fieldType, ref object value)
  547. {
  548. return ReadField(fieldType, ref value);
  549. }
  550. bool ICodedInputStream.IsAtEnd
  551. {
  552. get
  553. {
  554. string next;
  555. return PeekNext(out next) == false;
  556. }
  557. }
  558. bool ICodedInputStream.SkipField()
  559. {
  560. Skip();
  561. return true;
  562. }
  563. void ICodedInputStream.ReadStringArray(uint fieldTag, string fieldName, ICollection<string> list)
  564. {
  565. ReadArray(FieldType.String, fieldName, list);
  566. }
  567. void ICodedInputStream.ReadBytesArray(uint fieldTag, string fieldName, ICollection<ByteString> list)
  568. {
  569. ReadArray(FieldType.Bytes, fieldName, list);
  570. }
  571. void ICodedInputStream.ReadBoolArray(uint fieldTag, string fieldName, ICollection<bool> list)
  572. {
  573. ReadArray(FieldType.Bool, fieldName, list);
  574. }
  575. void ICodedInputStream.ReadInt32Array(uint fieldTag, string fieldName, ICollection<int> list)
  576. {
  577. ReadArray(FieldType.Int32, fieldName, list);
  578. }
  579. void ICodedInputStream.ReadSInt32Array(uint fieldTag, string fieldName, ICollection<int> list)
  580. {
  581. ReadArray(FieldType.SInt32, fieldName, list);
  582. }
  583. void ICodedInputStream.ReadUInt32Array(uint fieldTag, string fieldName, ICollection<uint> list)
  584. {
  585. ReadArray(FieldType.UInt32, fieldName, list);
  586. }
  587. void ICodedInputStream.ReadFixed32Array(uint fieldTag, string fieldName, ICollection<uint> list)
  588. {
  589. ReadArray(FieldType.Fixed32, fieldName, list);
  590. }
  591. void ICodedInputStream.ReadSFixed32Array(uint fieldTag, string fieldName, ICollection<int> list)
  592. {
  593. ReadArray(FieldType.SFixed32, fieldName, list);
  594. }
  595. void ICodedInputStream.ReadInt64Array(uint fieldTag, string fieldName, ICollection<long> list)
  596. {
  597. ReadArray(FieldType.Int64, fieldName, list);
  598. }
  599. void ICodedInputStream.ReadSInt64Array(uint fieldTag, string fieldName, ICollection<long> list)
  600. {
  601. ReadArray(FieldType.SInt64, fieldName, list);
  602. }
  603. void ICodedInputStream.ReadUInt64Array(uint fieldTag, string fieldName, ICollection<ulong> list)
  604. {
  605. ReadArray(FieldType.UInt64, fieldName, list);
  606. }
  607. void ICodedInputStream.ReadFixed64Array(uint fieldTag, string fieldName, ICollection<ulong> list)
  608. {
  609. ReadArray(FieldType.Fixed64, fieldName, list);
  610. }
  611. void ICodedInputStream.ReadSFixed64Array(uint fieldTag, string fieldName, ICollection<long> list)
  612. {
  613. ReadArray(FieldType.SFixed64, fieldName, list);
  614. }
  615. void ICodedInputStream.ReadDoubleArray(uint fieldTag, string fieldName, ICollection<double> list)
  616. {
  617. ReadArray(FieldType.Double, fieldName, list);
  618. }
  619. void ICodedInputStream.ReadFloatArray(uint fieldTag, string fieldName, ICollection<float> list)
  620. {
  621. ReadArray(FieldType.Float, fieldName, list);
  622. }
  623. #endregion
  624. }
  625. }