blob: d6e5c18976c1bbe795d1f628292f43908d0c4653 [file] [log] [blame]
csharptest4dc0dfb2011-06-10 18:01:34 -05001using System;
2using System.Collections.Generic;
3using System.Text;
4using 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 {
57 if (!_ready) return false;
58
59 object obj = _input.Current.Value;
60 if (obj is T)
61 value = (T)obj;
62 else
63 {
64 try
65 {
66 if (obj is IConvertible)
csharptest7fc785c2011-06-10 23:54:53 -050067 value = (T)Convert.ChangeType(obj, typeof(T), System.Globalization.CultureInfo.InvariantCulture);
csharptest4dc0dfb2011-06-10 18:01:34 -050068 else
69 value = (T)obj;
70 }
71 catch
72 {
73 _ready = _input.MoveNext();
74 return false;
75 }
76 }
77 _ready = _input.MoveNext();
78 return true;
79 }
80
81 /// <summary>
82 /// Returns true if it was able to read a Boolean from the input
83 /// </summary>
84 protected override bool Read(ref bool value)
85 {
86 return GetValue(ref value);
87 }
88
89 /// <summary>
90 /// Returns true if it was able to read a Int32 from the input
91 /// </summary>
92 protected override bool Read(ref int value)
93 {
94 return GetValue(ref value);
95 }
96
97 /// <summary>
98 /// Returns true if it was able to read a UInt32 from the input
99 /// </summary>
100 [CLSCompliant(false)]
101 protected override bool Read(ref uint value)
102 {
103 return GetValue(ref value);
104 }
105
106 /// <summary>
107 /// Returns true if it was able to read a Int64 from the input
108 /// </summary>
109 protected override bool Read(ref long value)
110 {
111 return GetValue(ref value);
112 }
113
114 /// <summary>
115 /// Returns true if it was able to read a UInt64 from the input
116 /// </summary>
117 [CLSCompliant(false)]
118 protected override bool Read(ref ulong value)
119 {
120 return GetValue(ref value);
121 }
122
123 /// <summary>
124 /// Returns true if it was able to read a Single from the input
125 /// </summary>
126 protected override bool Read(ref float value)
127 {
128 return GetValue(ref value);
129 }
130
131 /// <summary>
132 /// Returns true if it was able to read a Double from the input
133 /// </summary>
134 protected override bool Read(ref double value)
135 {
136 return GetValue(ref value);
137 }
138
139 /// <summary>
140 /// Returns true if it was able to read a String from the input
141 /// </summary>
142 protected override bool Read(ref string value)
143 {
144 return GetValue(ref value);
145 }
146
147 /// <summary>
148 /// Returns true if it was able to read a ByteString from the input
149 /// </summary>
150 protected override bool Read(ref ByteString value)
151 {
152 byte[] rawbytes = null;
153 if (GetValue(ref rawbytes))
154 {
155 value = ByteString.AttachBytes(rawbytes);
156 return true;
157 }
158 return false;
159 }
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
170 /// <summary>
171 /// Merges the input stream into the provided IBuilderLite
172 /// </summary>
173 protected override bool ReadMessage(IBuilderLite builder, ExtensionRegistry registry)
174 {
175 IDictionary<string, object> values = null;
176 if (GetValue(ref values))
177 {
178 new DictionaryReader(values).Merge(builder, registry);
179 return true;
180 }
181 return false;
182 }
183
184 public override bool ReadArray<T>(FieldType type, string field, ICollection<T> items)
185 {
186 object[] array = null;
187 if (GetValue(ref array))
188 {
csharptest7fc785c2011-06-10 23:54:53 -0500189 if (typeof(T) == typeof(ByteString))
190 {
191 ICollection<ByteString> output = (ICollection<ByteString>)items;
192 foreach (byte[] item in array)
193 output.Add(ByteString.CopyFrom(item));
194 }
195 else
196 {
197 foreach (T item in array)
198 items.Add(item);
199 }
csharptest4dc0dfb2011-06-10 18:01:34 -0500200 return true;
201 }
202 return false;
203 }
204
205 public override bool ReadEnumArray(string field, ICollection<object> items)
206 {
207 object[] array = null;
208 if (GetValue(ref array))
209 {
210 foreach (object item in array)
211 items.Add(item);
212 return true;
213 }
214 return false;
215 }
216
217 public override bool ReadMessageArray<T>(string field, ICollection<T> items, IMessageLite messageType, ExtensionRegistry registry)
218 {
219 object[] array = null;
220 if (GetValue(ref array))
221 {
222 foreach (IDictionary<string, object> item in array)
223 {
224 IBuilderLite builder = messageType.WeakCreateBuilderForType();
225 new DictionaryReader(item).Merge(builder);
226 items.Add((T)builder.WeakBuild());
227 }
228 return true;
229 }
230 return false;
231 }
232
233 public override bool ReadGroupArray<T>(string field, ICollection<T> items, IMessageLite messageType, ExtensionRegistry registry)
234 { return ReadMessageArray(field, items, messageType, registry); }
235 }
236}