blob: 8e4030e600393952b9bc64668c6d744566802e2b [file] [log] [blame]
csharptest2b868842011-06-10 14:41:47 -05001using System;
2using System.Collections.Generic;
3using Google.ProtocolBuffers.Descriptors;
4
5//Disable CS3011: only CLS-compliant members can be abstract
6#pragma warning disable 3011
7
8namespace Google.ProtocolBuffers.Serialization
9{
10 /// <summary>
11 /// Provides a base-class that provides some basic functionality for handling type dispatching
12 /// </summary>
13 public abstract class AbstractReader : ICodedInputStream
14 {
15 /// <summary>
16 /// Merges the contents of stream into the provided message builder
17 /// </summary>
18 public TBuilder Merge<TBuilder>(TBuilder builder) where TBuilder : IBuilderLite
19 { return Merge(builder, ExtensionRegistry.Empty); }
20
21 /// <summary>
22 /// Merges the contents of stream into the provided message builder
23 /// </summary>
24 public abstract TBuilder Merge<TBuilder>(TBuilder builder, ExtensionRegistry registry) where TBuilder : IBuilderLite;
25
26 /// <summary>
27 /// Peeks at the next field in the input stream and returns what information is available.
28 /// </summary>
29 /// <remarks>
30 /// This may be called multiple times without actually reading the field. Only after the field
31 /// is either read, or skipped, should PeekNext return a different value.
32 /// </remarks>
33 protected abstract bool PeekNext(out string field);
34
35 /// <summary>
36 /// Causes the reader to skip past this field
37 /// </summary>
38 protected abstract void Skip();
39
40 /// <summary>
41 /// Returns true if it was able to read a Boolean from the input
42 /// </summary>
43 protected abstract bool Read(ref bool value);
44
45 /// <summary>
46 /// Returns true if it was able to read a Int32 from the input
47 /// </summary>
48 protected abstract bool Read(ref int value);
49
50 /// <summary>
51 /// Returns true if it was able to read a UInt32 from the input
52 /// </summary>
53 [CLSCompliant(false)]
54 protected abstract bool Read(ref uint value);
55
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
61 /// <summary>
62 /// Returns true if it was able to read a UInt64 from the input
63 /// </summary>
64 [CLSCompliant(false)]
65 protected abstract bool Read(ref ulong value);
66
67 /// <summary>
68 /// Returns true if it was able to read a Single from the input
69 /// </summary>
70 protected abstract bool Read(ref float value);
71
72 /// <summary>
73 /// Returns true if it was able to read a Double from the input
74 /// </summary>
75 protected abstract bool Read(ref double value);
76
77 /// <summary>
78 /// Returns true if it was able to read a String from the input
79 /// </summary>
80 protected abstract bool Read(ref string value);
81
82 /// <summary>
83 /// Returns true if it was able to read a ByteString from the input
84 /// </summary>
85 protected abstract bool Read(ref ByteString value);
86
87 /// <summary>
88 /// returns true if it was able to read a single value into the value reference. The value
89 /// stored may be of type System.String, System.Int32, or an IEnumLite from the IEnumLiteMap.
90 /// </summary>
91 protected abstract bool ReadEnum(ref object value);
92
93 /// <summary>
94 /// Merges the input stream into the provided IBuilderLite
95 /// </summary>
96 protected abstract bool ReadMessage(IBuilderLite builder, ExtensionRegistry registry);
97
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
106 /// <summary>
107 /// Cursors through the array elements and stops at the end of the array
108 /// </summary>
109 protected virtual IEnumerable<string> ForeachArrayItem(string field)
110 {
111 string next = field;
112 while (true)
113 {
114 yield return next;
115
116 if (!PeekNext(out next) || next != field)
117 break;
118 }
119 }
120
121 /// <summary>
122 /// Reads an array of T messages
123 /// </summary>
124 public virtual bool ReadMessageArray<T>(string field, ICollection<T> items, IMessageLite messageType, 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
139 /// <summary>
140 /// Reads an array of T messages as a proto-buffer group
141 /// </summary>
142 public virtual bool ReadGroupArray<T>(string field, ICollection<T> items, IMessageLite messageType, 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
157 /// <summary>
158 /// Reads an array of System.Enum type T and adds them to the collection
159 /// </summary>
160 public virtual bool ReadEnumArray(string field, ICollection<object> items)
161 {
162 bool success = false;
163 foreach (string next in ForeachArrayItem(field))
164 {
165 object temp = null;
166 if (ReadEnum(ref temp))
167 {
168 items.Add(temp);
169 success |= true;
170 }
171 }
172 return success;
173 }
174
175 /// <summary>
176 /// Reads an array of T, where T is a primitive type defined by FieldType
177 /// </summary>
178 public virtual bool ReadArray<T>(FieldType type, string field, ICollection<T> items)
179 {
180 bool success = false;
181 foreach (string next in ForeachArrayItem(field))
182 {
183 object temp = null;
184 if (ReadField(type, ref temp))
185 {
186 items.Add((T)temp);
187 success |= true;
188 }
189 }
190 return success;
191 }
192
193 /// <summary>
194 /// returns true if it was able to read a single primitive value of FieldType into the value reference
195 /// </summary>
196 public virtual bool ReadField(FieldType type, ref object value)
197 {
198 switch (type)
199 {
200 case FieldType.Bool:
201 {
202 bool temp = false;
203 if (Read(ref temp))
204 value = temp;
205 else
206 return false;
207 break;
208 }
209 case FieldType.Int64:
210 case FieldType.SInt64:
211 case FieldType.SFixed64:
212 {
213 long temp = 0;
214 if (Read(ref temp))
215 value = temp;
216 else
217 return false;
218 break;
219 }
220 case FieldType.UInt64:
221 case FieldType.Fixed64:
222 {
223 ulong temp = 0;
224 if (Read(ref temp))
225 value = temp;
226 else
227 return false;
228 break;
229 }
230 case FieldType.Int32:
231 case FieldType.SInt32:
232 case FieldType.SFixed32:
233 {
234 int temp = 0;
235 if (Read(ref temp))
236 value = temp;
237 else
238 return false;
239 break;
240 }
241 case FieldType.UInt32:
242 case FieldType.Fixed32:
243 {
244 uint temp = 0;
245 if (Read(ref temp))
246 value = temp;
247 else
248 return false;
249 break;
250 }
251 case FieldType.Float:
252 {
253 float temp = float.NaN;
254 if (Read(ref temp))
255 value = temp;
256 else
257 return false;
258 break;
259 }
260 case FieldType.Double:
261 {
262 double temp = float.NaN;
263 if (Read(ref temp))
264 value = temp;
265 else
266 return false;
267 break;
268 }
269 case FieldType.String:
270 {
271 string temp = null;
272 if (Read(ref temp))
273 value = temp;
274 else
275 return false;
276 break;
277 }
278 case FieldType.Bytes:
279 {
280 ByteString temp = null;
281 if (Read(ref temp))
282 value = temp;
283 else
284 return false;
285 break;
286 }
287 default:
288 throw InvalidProtocolBufferException.InvalidTag();
289 }
290 return true;
291 }
292
293 #region ICodedInputStream Members
294
295 bool ICodedInputStream.ReadTag(out uint fieldTag, out string fieldName)
296 {
297 fieldTag = 0;
298 if (PeekNext(out fieldName))
299 {
300 return true;
301 }
302 return false;
303 }
304
305 bool ICodedInputStream.ReadDouble(ref double value)
306 { return Read(ref value); }
307
308 bool ICodedInputStream.ReadFloat(ref float value)
309 { return Read(ref value); }
310
311 bool ICodedInputStream.ReadUInt64(ref ulong value)
312 { return Read(ref value); }
313
314 bool ICodedInputStream.ReadInt64(ref long value)
315 { return Read(ref value); }
316
317 bool ICodedInputStream.ReadInt32(ref int value)
318 { return Read(ref value); }
319
320 bool ICodedInputStream.ReadFixed64(ref ulong value)
321 { return Read(ref value); }
322
323 bool ICodedInputStream.ReadFixed32(ref uint value)
324 { return Read(ref value); }
325
326 bool ICodedInputStream.ReadBool(ref bool value)
327 { return Read(ref value); }
328
329 bool ICodedInputStream.ReadString(ref string value)
330 { return Read(ref value); }
331
332 void ICodedInputStream.ReadGroup(int fieldNumber, IBuilderLite builder, ExtensionRegistry extensionRegistry)
333 { ReadGroup(builder, extensionRegistry); }
334
335 void ICodedInputStream.ReadUnknownGroup(int fieldNumber, IBuilderLite builder)
336 { throw new NotSupportedException(); }
337
338 void ICodedInputStream.ReadMessage(IBuilderLite builder, ExtensionRegistry extensionRegistry)
339 { ReadMessage(builder, extensionRegistry); }
340
341 bool ICodedInputStream.ReadBytes(ref ByteString value)
342 { return Read(ref value); }
343
344 bool ICodedInputStream.ReadUInt32(ref uint value)
345 { return Read(ref value); }
346
347 bool ICodedInputStream.ReadEnum(ref IEnumLite value, out object unknown, IEnumLiteMap mapping)
348 {
349 value = null;
350 unknown = null;
351 if(ReadEnum(ref unknown))
352 {
353 if (unknown is int) value = mapping.FindValueByNumber((int)unknown);
354 else if (unknown is string) value = mapping.FindValueByName((string)unknown);
355 return value != null;
356 }
357 return false;
358 }
359
360 bool ICodedInputStream.ReadEnum<T>(ref T value, out object rawValue)
361 {
362 rawValue = null;
363 if (ReadEnum(ref rawValue))
364 {
365 if (Enum.IsDefined(typeof(T), rawValue))
366 {
367 if (rawValue is int)
368 value = (T)rawValue;
369 else if (rawValue is string)
370 value = (T)Enum.Parse(typeof(T), (string)rawValue, false);
371 else
372 {
373 value = default(T);
374 return false;
375 }
376 return true;
377 }
378 }
379 return false;
380 }
381
382 bool ICodedInputStream.ReadSFixed32(ref int value)
383 { return Read(ref value); }
384
385 bool ICodedInputStream.ReadSFixed64(ref long value)
386 { return Read(ref value); }
387
388 bool ICodedInputStream.ReadSInt32(ref int value)
389 { return Read(ref value); }
390
391 bool ICodedInputStream.ReadSInt64(ref long value)
392 { return Read(ref value); }
393
394 void ICodedInputStream.ReadPrimitiveArray(FieldType fieldType, uint fieldTag, string fieldName, ICollection<object> list)
395 { ReadArray(fieldType, fieldName, list); }
396
397 void ICodedInputStream.ReadEnumArray(uint fieldTag, string fieldName, ICollection<IEnumLite> list, out ICollection<object> unknown, IEnumLiteMap mapping)
398 {
399 unknown = null;
400 List<object> array = new List<object>();
401 if (ReadEnumArray(fieldName, array))
402 {
403 foreach (object rawValue in array)
404 {
405 IEnumLite item = null;
406 if (rawValue is int) item = mapping.FindValueByNumber((int)rawValue);
407 else if (rawValue is string) item = mapping.FindValueByName((string)rawValue);
408
409 if (item != null)
410 list.Add(item);
411 else
412 {
413 if (unknown == null) unknown = new List<object>();
414 unknown.Add(rawValue);
415 }
416 }
417 }
418 }
419
420 void ICodedInputStream.ReadEnumArray<T>(uint fieldTag, string fieldName, ICollection<T> list, out ICollection<object> unknown)
421 {
422 unknown = null;
423 List<object> array = new List<object>();
424 if (ReadEnumArray(fieldName, array))
425 {
426 foreach (object rawValue in array)
427 {
428 if (rawValue is int)
429 list.Add((T)rawValue);
430 else if (rawValue is string)
431 list.Add((T)Enum.Parse(typeof(T), (string)rawValue, false));
432 else
433 {
434 if (unknown == null) unknown = new List<object>();
435 unknown.Add(rawValue);
436 }
437 }
438 }
439 }
440
441 void ICodedInputStream.ReadMessageArray<T>(uint fieldTag, string fieldName, ICollection<T> list, T messageType, ExtensionRegistry registry)
442 { ReadMessageArray(fieldName, list, messageType, registry); }
443
444 void ICodedInputStream.ReadGroupArray<T>(uint fieldTag, string fieldName, ICollection<T> list, T messageType, ExtensionRegistry registry)
445 { ReadGroupArray(fieldName, list, messageType, registry); }
446
447 bool ICodedInputStream.ReadPrimitiveField(FieldType fieldType, ref object value)
448 { return ReadField(fieldType, ref value); }
449
450 bool ICodedInputStream.IsAtEnd
451 {
452 get { string next; return PeekNext(out next) == false; }
453 }
454
455 bool ICodedInputStream.SkipField()
456 {
457 Skip();
458 return true;
459 }
460
461 void ICodedInputStream.ReadStringArray(uint fieldTag, string fieldName, ICollection<string> list)
462 { ReadArray(FieldType.String, fieldName, list); }
463
464 void ICodedInputStream.ReadBytesArray(uint fieldTag, string fieldName, ICollection<ByteString> list)
465 { ReadArray(FieldType.Bytes, fieldName, list); }
466
467 void ICodedInputStream.ReadBoolArray(uint fieldTag, string fieldName, ICollection<bool> list)
468 { ReadArray(FieldType.Bool, fieldName, list); }
469
470 void ICodedInputStream.ReadInt32Array(uint fieldTag, string fieldName, ICollection<int> list)
471 { ReadArray(FieldType.Int32, fieldName, list); }
472
473 void ICodedInputStream.ReadSInt32Array(uint fieldTag, string fieldName, ICollection<int> list)
474 { ReadArray(FieldType.SInt32, fieldName, list); }
475
476 void ICodedInputStream.ReadUInt32Array(uint fieldTag, string fieldName, ICollection<uint> list)
477 { ReadArray(FieldType.UInt32, fieldName, list); }
478
479 void ICodedInputStream.ReadFixed32Array(uint fieldTag, string fieldName, ICollection<uint> list)
480 { ReadArray(FieldType.Fixed32, fieldName, list); }
481
482 void ICodedInputStream.ReadSFixed32Array(uint fieldTag, string fieldName, ICollection<int> list)
483 { ReadArray(FieldType.SFixed32, fieldName, list); }
484
485 void ICodedInputStream.ReadInt64Array(uint fieldTag, string fieldName, ICollection<long> list)
486 { ReadArray(FieldType.Int64, fieldName, list); }
487
488 void ICodedInputStream.ReadSInt64Array(uint fieldTag, string fieldName, ICollection<long> list)
489 { ReadArray(FieldType.SInt64, fieldName, list); }
490
491 void ICodedInputStream.ReadUInt64Array(uint fieldTag, string fieldName, ICollection<ulong> list)
492 { ReadArray(FieldType.UInt64, fieldName, list); }
493
494 void ICodedInputStream.ReadFixed64Array(uint fieldTag, string fieldName, ICollection<ulong> list)
495 { ReadArray(FieldType.Fixed64, fieldName, list); }
496
497 void ICodedInputStream.ReadSFixed64Array(uint fieldTag, string fieldName, ICollection<long> list)
498 { ReadArray(FieldType.SFixed64, fieldName, list); }
499
500 void ICodedInputStream.ReadDoubleArray(uint fieldTag, string fieldName, ICollection<double> list)
501 { ReadArray(FieldType.Double, fieldName, list); }
502
503 void ICodedInputStream.ReadFloatArray(uint fieldTag, string fieldName, ICollection<float> list)
504 { ReadArray(FieldType.Float, fieldName, list); }
505
506 #endregion
507 }
508}