blob: cc5c680cb31f16a0ab11c7b55ab38fa4a06111fd [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>
26 /// Merges the contents of stream into the provided message builder
27 /// </summary>
28 public override TBuilder Merge<TBuilder>(TBuilder builder, ExtensionRegistry registry)
29 {
30 builder.WeakMergeFrom(this, registry);
31 return builder;
32 }
33
34 /// <summary>
35 /// Peeks at the next field in the input stream and returns what information is available.
36 /// </summary>
37 /// <remarks>
38 /// This may be called multiple times without actually reading the field. Only after the field
39 /// is either read, or skipped, should PeekNext return a different value.
40 /// </remarks>
41 protected override bool PeekNext(out string field)
42 {
43 field = _ready ? _input.Current.Key : null;
44 return _ready;
45 }
46
47 /// <summary>
48 /// Causes the reader to skip past this field
49 /// </summary>
50 protected override void Skip()
51 {
52 _ready = _input.MoveNext();
53 }
54
55 private bool GetValue<T>(ref T value)
56 {
csharptest74c5e0c2011-07-14 13:06:22 -050057 if (!_ready)
58 {
59 return false;
60 }
csharptest4dc0dfb2011-06-10 18:01:34 -050061
62 object obj = _input.Current.Value;
63 if (obj is T)
csharptest74c5e0c2011-07-14 13:06:22 -050064 {
65 value = (T) obj;
66 }
csharptest4dc0dfb2011-06-10 18:01:34 -050067 else
68 {
csharptest74c5e0c2011-07-14 13:06:22 -050069 try
csharptest4dc0dfb2011-06-10 18:01:34 -050070 {
71 if (obj is IConvertible)
csharptest74c5e0c2011-07-14 13:06:22 -050072 {
73 value = (T) Convert.ChangeType(obj, typeof (T), CultureInfo.InvariantCulture);
74 }
csharptest4dc0dfb2011-06-10 18:01:34 -050075 else
csharptest74c5e0c2011-07-14 13:06:22 -050076 {
77 value = (T) obj;
78 }
csharptest4dc0dfb2011-06-10 18:01:34 -050079 }
80 catch
81 {
csharptest74c5e0c2011-07-14 13:06:22 -050082 _ready = _input.MoveNext();
csharptest4dc0dfb2011-06-10 18:01:34 -050083 return false;
84 }
85 }
86 _ready = _input.MoveNext();
87 return true;
88 }
89
90 /// <summary>
91 /// Returns true if it was able to read a Boolean from the input
92 /// </summary>
93 protected override bool Read(ref bool value)
94 {
csharptest74c5e0c2011-07-14 13:06:22 -050095 return GetValue(ref value);
csharptest4dc0dfb2011-06-10 18:01:34 -050096 }
97
98 /// <summary>
99 /// Returns true if it was able to read a Int32 from the input
100 /// </summary>
101 protected override bool Read(ref int value)
102 {
103 return GetValue(ref value);
104 }
105
106 /// <summary>
107 /// Returns true if it was able to read a UInt32 from the input
108 /// </summary>
109 [CLSCompliant(false)]
110 protected override bool Read(ref uint value)
111 {
112 return GetValue(ref value);
113 }
114
115 /// <summary>
116 /// Returns true if it was able to read a Int64 from the input
117 /// </summary>
118 protected override bool Read(ref long value)
119 {
120 return GetValue(ref value);
121 }
122
123 /// <summary>
124 /// Returns true if it was able to read a UInt64 from the input
125 /// </summary>
126 [CLSCompliant(false)]
127 protected override bool Read(ref ulong value)
128 {
129 return GetValue(ref value);
130 }
131
132 /// <summary>
133 /// Returns true if it was able to read a Single from the input
134 /// </summary>
135 protected override bool Read(ref float value)
136 {
137 return GetValue(ref value);
138 }
139
140 /// <summary>
141 /// Returns true if it was able to read a Double from the input
142 /// </summary>
143 protected override bool Read(ref double value)
144 {
145 return GetValue(ref value);
146 }
147
148 /// <summary>
149 /// Returns true if it was able to read a String from the input
150 /// </summary>
151 protected override bool Read(ref string value)
152 {
153 return GetValue(ref value);
154 }
155
156 /// <summary>
157 /// Returns true if it was able to read a ByteString from the input
158 /// </summary>
159 protected override bool Read(ref ByteString value)
160 {
161 byte[] rawbytes = null;
162 if (GetValue(ref rawbytes))
163 {
csharptest0f3540e2011-08-05 20:40:14 -0500164 value = ByteString.CopyFrom(rawbytes);
csharptest4dc0dfb2011-06-10 18:01:34 -0500165 return true;
166 }
167 return false;
168 }
169
170 /// <summary>
171 /// returns true if it was able to read a single value into the value reference. The value
172 /// stored may be of type System.String, System.Int32, or an IEnumLite from the IEnumLiteMap.
173 /// </summary>
174 protected override bool ReadEnum(ref object value)
175 {
176 return GetValue(ref value);
177 }
178
179 /// <summary>
180 /// Merges the input stream into the provided IBuilderLite
181 /// </summary>
182 protected override bool ReadMessage(IBuilderLite builder, ExtensionRegistry registry)
183 {
184 IDictionary<string, object> values = null;
185 if (GetValue(ref values))
186 {
187 new DictionaryReader(values).Merge(builder, registry);
188 return true;
189 }
190 return false;
191 }
192
193 public override bool ReadArray<T>(FieldType type, string field, ICollection<T> items)
194 {
195 object[] array = null;
196 if (GetValue(ref array))
197 {
csharptest74c5e0c2011-07-14 13:06:22 -0500198 if (typeof (T) == typeof (ByteString))
csharptest7fc785c2011-06-10 23:54:53 -0500199 {
csharptest74c5e0c2011-07-14 13:06:22 -0500200 ICollection<ByteString> output = (ICollection<ByteString>) items;
csharptest7fc785c2011-06-10 23:54:53 -0500201 foreach (byte[] item in array)
csharptest74c5e0c2011-07-14 13:06:22 -0500202 {
csharptest7fc785c2011-06-10 23:54:53 -0500203 output.Add(ByteString.CopyFrom(item));
csharptest74c5e0c2011-07-14 13:06:22 -0500204 }
csharptest7fc785c2011-06-10 23:54:53 -0500205 }
206 else
207 {
208 foreach (T item in array)
csharptest74c5e0c2011-07-14 13:06:22 -0500209 {
csharptest7fc785c2011-06-10 23:54:53 -0500210 items.Add(item);
csharptest74c5e0c2011-07-14 13:06:22 -0500211 }
csharptest7fc785c2011-06-10 23:54:53 -0500212 }
csharptest4dc0dfb2011-06-10 18:01:34 -0500213 return true;
214 }
215 return false;
216 }
csharptest74c5e0c2011-07-14 13:06:22 -0500217
csharptest4dc0dfb2011-06-10 18:01:34 -0500218 public override bool ReadEnumArray(string field, ICollection<object> items)
219 {
220 object[] array = null;
221 if (GetValue(ref array))
222 {
223 foreach (object item in array)
csharptest74c5e0c2011-07-14 13:06:22 -0500224 {
csharptest4dc0dfb2011-06-10 18:01:34 -0500225 items.Add(item);
csharptest74c5e0c2011-07-14 13:06:22 -0500226 }
csharptest4dc0dfb2011-06-10 18:01:34 -0500227 return true;
228 }
229 return false;
230 }
231
csharptest74c5e0c2011-07-14 13:06:22 -0500232 public override bool ReadMessageArray<T>(string field, ICollection<T> items, IMessageLite messageType,
233 ExtensionRegistry registry)
csharptest4dc0dfb2011-06-10 18:01:34 -0500234 {
235 object[] array = null;
236 if (GetValue(ref array))
237 {
238 foreach (IDictionary<string, object> item in array)
239 {
240 IBuilderLite builder = messageType.WeakCreateBuilderForType();
241 new DictionaryReader(item).Merge(builder);
csharptest74c5e0c2011-07-14 13:06:22 -0500242 items.Add((T) builder.WeakBuild());
csharptest4dc0dfb2011-06-10 18:01:34 -0500243 }
244 return true;
245 }
246 return false;
247 }
248
csharptest74c5e0c2011-07-14 13:06:22 -0500249 public override bool ReadGroupArray<T>(string field, ICollection<T> items, IMessageLite messageType,
250 ExtensionRegistry registry)
251 {
252 return ReadMessageArray(field, items, messageType, registry);
253 }
csharptest4dc0dfb2011-06-10 18:01:34 -0500254 }
csharptest74c5e0c2011-07-14 13:06:22 -0500255}