blob: f606bc9bdbc6a94e0c3b736a7054f3db583aac19 [file] [log] [blame]
csharptest4dc0dfb2011-06-10 18:01:34 -05001using System;
2using System.Collections.Generic;
csharptest74c5e0c2011-07-14 13:06:22 -05003using System.Globalization;
csharptest4dc0dfb2011-06-10 18:01:34 -05004using Google.ProtocolBuffers.Descriptors;
5
6namespace Google.ProtocolBuffers.Serialization
7{
8 /// <summary>
9 /// Allows reading messages from a name/value dictionary
10 /// </summary>
11 public class DictionaryReader : AbstractReader
12 {
13 private readonly IEnumerator<KeyValuePair<string, object>> _input;
14 private bool _ready;
15
16 /// <summary>
17 /// Creates a dictionary reader from an enumeration of KeyValuePair data, like an IDictionary
18 /// </summary>
19 public DictionaryReader(IEnumerable<KeyValuePair<string, object>> input)
20 {
21 _input = input.GetEnumerator();
22 _ready = _input.MoveNext();
23 }
24
25 /// <summary>
csharptestc2d2c1a2011-09-08 20:02:11 -050026 /// No-op
27 /// </summary>
28 public override AbstractReader ReadStartMessage()
29 {
30 return this;
31 }
32
33 /// <summary>
34 /// No-op
35 /// </summary>
36 public override void ReadEndMessage()
37 {
38 }
39
40 /// <summary>
csharptest4dc0dfb2011-06-10 18:01:34 -050041 /// Merges the contents of stream into the provided message builder
42 /// </summary>
43 public override TBuilder Merge<TBuilder>(TBuilder builder, ExtensionRegistry registry)
44 {
45 builder.WeakMergeFrom(this, registry);
46 return builder;
47 }
48
49 /// <summary>
50 /// Peeks at the next field in the input stream and returns what information is available.
51 /// </summary>
52 /// <remarks>
53 /// This may be called multiple times without actually reading the field. Only after the field
54 /// is either read, or skipped, should PeekNext return a different value.
55 /// </remarks>
56 protected override bool PeekNext(out string field)
57 {
58 field = _ready ? _input.Current.Key : null;
59 return _ready;
60 }
61
62 /// <summary>
63 /// Causes the reader to skip past this field
64 /// </summary>
65 protected override void Skip()
66 {
67 _ready = _input.MoveNext();
68 }
69
70 private bool GetValue<T>(ref T value)
71 {
csharptest74c5e0c2011-07-14 13:06:22 -050072 if (!_ready)
73 {
74 return false;
75 }
csharptest4dc0dfb2011-06-10 18:01:34 -050076
77 object obj = _input.Current.Value;
78 if (obj is T)
csharptest74c5e0c2011-07-14 13:06:22 -050079 {
80 value = (T) obj;
81 }
csharptest4dc0dfb2011-06-10 18:01:34 -050082 else
83 {
csharptest74c5e0c2011-07-14 13:06:22 -050084 try
csharptest4dc0dfb2011-06-10 18:01:34 -050085 {
86 if (obj is IConvertible)
csharptest74c5e0c2011-07-14 13:06:22 -050087 {
88 value = (T) Convert.ChangeType(obj, typeof (T), CultureInfo.InvariantCulture);
89 }
csharptest4dc0dfb2011-06-10 18:01:34 -050090 else
csharptest74c5e0c2011-07-14 13:06:22 -050091 {
92 value = (T) obj;
93 }
csharptest4dc0dfb2011-06-10 18:01:34 -050094 }
95 catch
96 {
csharptest74c5e0c2011-07-14 13:06:22 -050097 _ready = _input.MoveNext();
csharptest4dc0dfb2011-06-10 18:01:34 -050098 return false;
99 }
100 }
101 _ready = _input.MoveNext();
102 return true;
103 }
104
105 /// <summary>
106 /// Returns true if it was able to read a Boolean from the input
107 /// </summary>
108 protected override bool Read(ref bool value)
109 {
csharptest74c5e0c2011-07-14 13:06:22 -0500110 return GetValue(ref value);
csharptest4dc0dfb2011-06-10 18:01:34 -0500111 }
112
113 /// <summary>
114 /// Returns true if it was able to read a Int32 from the input
115 /// </summary>
116 protected override bool Read(ref int value)
117 {
118 return GetValue(ref value);
119 }
120
121 /// <summary>
122 /// Returns true if it was able to read a UInt32 from the input
123 /// </summary>
124 [CLSCompliant(false)]
125 protected override bool Read(ref uint value)
126 {
127 return GetValue(ref value);
128 }
129
130 /// <summary>
131 /// Returns true if it was able to read a Int64 from the input
132 /// </summary>
133 protected override bool Read(ref long value)
134 {
135 return GetValue(ref value);
136 }
137
138 /// <summary>
139 /// Returns true if it was able to read a UInt64 from the input
140 /// </summary>
141 [CLSCompliant(false)]
142 protected override bool Read(ref ulong value)
143 {
144 return GetValue(ref value);
145 }
146
147 /// <summary>
148 /// Returns true if it was able to read a Single from the input
149 /// </summary>
150 protected override bool Read(ref float value)
151 {
152 return GetValue(ref value);
153 }
154
155 /// <summary>
156 /// Returns true if it was able to read a Double from the input
157 /// </summary>
158 protected override bool Read(ref double value)
159 {
160 return GetValue(ref value);
161 }
162
163 /// <summary>
164 /// Returns true if it was able to read a String from the input
165 /// </summary>
166 protected override bool Read(ref string value)
167 {
168 return GetValue(ref value);
169 }
170
171 /// <summary>
172 /// Returns true if it was able to read a ByteString from the input
173 /// </summary>
174 protected override bool Read(ref ByteString value)
175 {
176 byte[] rawbytes = null;
177 if (GetValue(ref rawbytes))
178 {
csharptest0f3540e2011-08-05 20:40:14 -0500179 value = ByteString.CopyFrom(rawbytes);
csharptest4dc0dfb2011-06-10 18:01:34 -0500180 return true;
181 }
182 return false;
183 }
184
185 /// <summary>
186 /// returns true if it was able to read a single value into the value reference. The value
187 /// stored may be of type System.String, System.Int32, or an IEnumLite from the IEnumLiteMap.
188 /// </summary>
189 protected override bool ReadEnum(ref object value)
190 {
191 return GetValue(ref value);
192 }
193
194 /// <summary>
195 /// Merges the input stream into the provided IBuilderLite
196 /// </summary>
197 protected override bool ReadMessage(IBuilderLite builder, ExtensionRegistry registry)
198 {
199 IDictionary<string, object> values = null;
200 if (GetValue(ref values))
201 {
202 new DictionaryReader(values).Merge(builder, registry);
203 return true;
204 }
205 return false;
206 }
207
208 public override bool ReadArray<T>(FieldType type, string field, ICollection<T> items)
209 {
210 object[] array = null;
211 if (GetValue(ref array))
212 {
csharptest74c5e0c2011-07-14 13:06:22 -0500213 if (typeof (T) == typeof (ByteString))
csharptest7fc785c2011-06-10 23:54:53 -0500214 {
csharptest74c5e0c2011-07-14 13:06:22 -0500215 ICollection<ByteString> output = (ICollection<ByteString>) items;
csharptest7fc785c2011-06-10 23:54:53 -0500216 foreach (byte[] item in array)
csharptest74c5e0c2011-07-14 13:06:22 -0500217 {
csharptest7fc785c2011-06-10 23:54:53 -0500218 output.Add(ByteString.CopyFrom(item));
csharptest74c5e0c2011-07-14 13:06:22 -0500219 }
csharptest7fc785c2011-06-10 23:54:53 -0500220 }
221 else
222 {
223 foreach (T item in array)
csharptest74c5e0c2011-07-14 13:06:22 -0500224 {
csharptest7fc785c2011-06-10 23:54:53 -0500225 items.Add(item);
csharptest74c5e0c2011-07-14 13:06:22 -0500226 }
csharptest7fc785c2011-06-10 23:54:53 -0500227 }
csharptest4dc0dfb2011-06-10 18:01:34 -0500228 return true;
229 }
230 return false;
231 }
csharptest74c5e0c2011-07-14 13:06:22 -0500232
csharptest4dc0dfb2011-06-10 18:01:34 -0500233 public override bool ReadEnumArray(string field, ICollection<object> items)
234 {
235 object[] array = null;
236 if (GetValue(ref array))
237 {
238 foreach (object item in array)
csharptest74c5e0c2011-07-14 13:06:22 -0500239 {
csharptest4dc0dfb2011-06-10 18:01:34 -0500240 items.Add(item);
csharptest74c5e0c2011-07-14 13:06:22 -0500241 }
csharptest4dc0dfb2011-06-10 18:01:34 -0500242 return true;
243 }
244 return false;
245 }
246
csharptest74c5e0c2011-07-14 13:06:22 -0500247 public override bool ReadMessageArray<T>(string field, ICollection<T> items, IMessageLite messageType,
248 ExtensionRegistry registry)
csharptest4dc0dfb2011-06-10 18:01:34 -0500249 {
250 object[] array = null;
251 if (GetValue(ref array))
252 {
253 foreach (IDictionary<string, object> item in array)
254 {
255 IBuilderLite builder = messageType.WeakCreateBuilderForType();
256 new DictionaryReader(item).Merge(builder);
csharptest74c5e0c2011-07-14 13:06:22 -0500257 items.Add((T) builder.WeakBuild());
csharptest4dc0dfb2011-06-10 18:01:34 -0500258 }
259 return true;
260 }
261 return false;
262 }
263
csharptest74c5e0c2011-07-14 13:06:22 -0500264 public override bool ReadGroupArray<T>(string field, ICollection<T> items, IMessageLite messageType,
265 ExtensionRegistry registry)
266 {
267 return ReadMessageArray(field, items, messageType, registry);
268 }
csharptest4dc0dfb2011-06-10 18:01:34 -0500269 }
csharptest74c5e0c2011-07-14 13:06:22 -0500270}