DictionaryReader.cs 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Globalization;
  4. using Google.ProtocolBuffers.Descriptors;
  5. namespace Google.ProtocolBuffers.Serialization
  6. {
  7. /// <summary>
  8. /// Allows reading messages from a name/value dictionary
  9. /// </summary>
  10. public class DictionaryReader : AbstractReader
  11. {
  12. private readonly IEnumerator<KeyValuePair<string, object>> _input;
  13. private bool _ready;
  14. /// <summary>
  15. /// Creates a dictionary reader from an enumeration of KeyValuePair data, like an IDictionary
  16. /// </summary>
  17. public DictionaryReader(IEnumerable<KeyValuePair<string, object>> input)
  18. {
  19. _input = input.GetEnumerator();
  20. _ready = _input.MoveNext();
  21. }
  22. /// <summary>
  23. /// No-op
  24. /// </summary>
  25. public override void ReadMessageStart()
  26. { }
  27. /// <summary>
  28. /// No-op
  29. /// </summary>
  30. public override void ReadMessageEnd()
  31. { }
  32. /// <summary>
  33. /// Merges the contents of stream into the provided message builder
  34. /// </summary>
  35. public override TBuilder Merge<TBuilder>(TBuilder builder, ExtensionRegistry registry)
  36. {
  37. builder.WeakMergeFrom(this, registry);
  38. return builder;
  39. }
  40. /// <summary>
  41. /// Peeks at the next field in the input stream and returns what information is available.
  42. /// </summary>
  43. /// <remarks>
  44. /// This may be called multiple times without actually reading the field. Only after the field
  45. /// is either read, or skipped, should PeekNext return a different value.
  46. /// </remarks>
  47. protected override bool PeekNext(out string field)
  48. {
  49. field = _ready ? _input.Current.Key : null;
  50. return _ready;
  51. }
  52. /// <summary>
  53. /// Causes the reader to skip past this field
  54. /// </summary>
  55. protected override void Skip()
  56. {
  57. _ready = _input.MoveNext();
  58. }
  59. private bool GetValue<T>(ref T value)
  60. {
  61. if (!_ready)
  62. {
  63. return false;
  64. }
  65. object obj = _input.Current.Value;
  66. if (obj is T)
  67. {
  68. value = (T) obj;
  69. }
  70. else
  71. {
  72. try
  73. {
  74. if (obj is IConvertible)
  75. {
  76. value = (T)Convert.ChangeType(obj, typeof(T), FrameworkPortability.InvariantCulture);
  77. }
  78. else
  79. {
  80. value = (T) obj;
  81. }
  82. }
  83. catch
  84. {
  85. _ready = _input.MoveNext();
  86. return false;
  87. }
  88. }
  89. _ready = _input.MoveNext();
  90. return true;
  91. }
  92. /// <summary>
  93. /// Returns true if it was able to read a Boolean from the input
  94. /// </summary>
  95. protected override bool Read(ref bool value)
  96. {
  97. return GetValue(ref value);
  98. }
  99. /// <summary>
  100. /// Returns true if it was able to read a Int32 from the input
  101. /// </summary>
  102. protected override bool Read(ref int value)
  103. {
  104. return GetValue(ref value);
  105. }
  106. /// <summary>
  107. /// Returns true if it was able to read a UInt32 from the input
  108. /// </summary>
  109. protected override bool Read(ref uint value)
  110. {
  111. return GetValue(ref value);
  112. }
  113. /// <summary>
  114. /// Returns true if it was able to read a Int64 from the input
  115. /// </summary>
  116. protected override bool Read(ref long value)
  117. {
  118. return GetValue(ref value);
  119. }
  120. /// <summary>
  121. /// Returns true if it was able to read a UInt64 from the input
  122. /// </summary>
  123. protected override bool Read(ref ulong value)
  124. {
  125. return GetValue(ref value);
  126. }
  127. /// <summary>
  128. /// Returns true if it was able to read a Single from the input
  129. /// </summary>
  130. protected override bool Read(ref float value)
  131. {
  132. return GetValue(ref value);
  133. }
  134. /// <summary>
  135. /// Returns true if it was able to read a Double from the input
  136. /// </summary>
  137. protected override bool Read(ref double value)
  138. {
  139. return GetValue(ref value);
  140. }
  141. /// <summary>
  142. /// Returns true if it was able to read a String from the input
  143. /// </summary>
  144. protected override bool Read(ref string value)
  145. {
  146. return GetValue(ref value);
  147. }
  148. /// <summary>
  149. /// Returns true if it was able to read a ByteString from the input
  150. /// </summary>
  151. protected override bool Read(ref ByteString value)
  152. {
  153. byte[] rawbytes = null;
  154. if (GetValue(ref rawbytes))
  155. {
  156. value = ByteString.CopyFrom(rawbytes);
  157. return true;
  158. }
  159. return false;
  160. }
  161. /// <summary>
  162. /// returns true if it was able to read a single value into the value reference. The value
  163. /// stored may be of type System.String, System.Int32, or an IEnumLite from the IEnumLiteMap.
  164. /// </summary>
  165. protected override bool ReadEnum(ref object value)
  166. {
  167. return GetValue(ref value);
  168. }
  169. /// <summary>
  170. /// Merges the input stream into the provided IBuilderLite
  171. /// </summary>
  172. protected override bool ReadMessage(IBuilderLite builder, ExtensionRegistry registry)
  173. {
  174. IDictionary<string, object> values = null;
  175. if (GetValue(ref values))
  176. {
  177. new DictionaryReader(values).Merge(builder, registry);
  178. return true;
  179. }
  180. return false;
  181. }
  182. public override bool ReadArray<T>(FieldType type, string field, ICollection<T> items)
  183. {
  184. object[] array = null;
  185. if (GetValue(ref array))
  186. {
  187. if (typeof(T) == typeof(ByteString))
  188. {
  189. ICollection<ByteString> output = (ICollection<ByteString>) items;
  190. foreach (byte[] item in array)
  191. {
  192. output.Add(ByteString.CopyFrom(item));
  193. }
  194. }
  195. else
  196. {
  197. foreach (T item in array)
  198. {
  199. items.Add(item);
  200. }
  201. }
  202. return true;
  203. }
  204. return false;
  205. }
  206. public override bool ReadEnumArray(string field, ICollection<object> items)
  207. {
  208. object[] array = null;
  209. if (GetValue(ref array))
  210. {
  211. foreach (object item in array)
  212. {
  213. items.Add(item);
  214. }
  215. return true;
  216. }
  217. return false;
  218. }
  219. public override bool ReadMessageArray<T>(string field, ICollection<T> items, IMessageLite messageType,
  220. ExtensionRegistry registry)
  221. {
  222. object[] array = null;
  223. if (GetValue(ref array))
  224. {
  225. foreach (IDictionary<string, object> item in array)
  226. {
  227. IBuilderLite builder = messageType.WeakCreateBuilderForType();
  228. new DictionaryReader(item).Merge(builder);
  229. items.Add((T) builder.WeakBuild());
  230. }
  231. return true;
  232. }
  233. return false;
  234. }
  235. public override bool ReadGroupArray<T>(string field, ICollection<T> items, IMessageLite messageType,
  236. ExtensionRegistry registry)
  237. {
  238. return ReadMessageArray(field, items, messageType, registry);
  239. }
  240. }
  241. }