20
|
1 //
|
|
2 // Copyright 2011 Kazuki Oikawa
|
|
3 //
|
|
4 // Licensed under the Apache License, Version 2.0 (the "License");
|
|
5 // you may not use this file except in compliance with the License.
|
|
6 // You may obtain a copy of the License at
|
|
7 //
|
|
8 // http://www.apache.org/licenses/LICENSE-2.0
|
|
9 //
|
|
10 // Unless required by applicable law or agreed to in writing, software
|
|
11 // distributed under the License is distributed on an "AS IS" BASIS,
|
|
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13 // See the License for the specific language governing permissions and
|
|
14 // limitations under the License.
|
|
15 //
|
|
16
|
|
17 using System;
|
|
18 using System.Collections.Generic;
|
|
19 using System.IO;
|
|
20 using System.Reflection;
|
|
21 using System.Reflection.Emit;
|
|
22 using System.Threading;
|
|
23 using MsgPack.Compiler;
|
|
24
|
|
25 namespace MsgPack
|
|
26 {
|
|
27 public class CompiledPacker
|
|
28 {
|
|
29 static PackerBase _publicFieldPacker, _allFieldPacker;
|
|
30 PackerBase _packer;
|
|
31
|
|
32 static CompiledPacker ()
|
|
33 {
|
|
34 _publicFieldPacker = new MethodBuilderPacker ();
|
|
35 _allFieldPacker = new DynamicMethodPacker ();
|
|
36 }
|
|
37
|
|
38 public CompiledPacker () : this (false) {}
|
|
39 public CompiledPacker (bool packPrivateField)
|
|
40 {
|
|
41 _packer = (packPrivateField ? _allFieldPacker : _publicFieldPacker);
|
|
42 }
|
|
43
|
|
44 public void Prepare<T> ()
|
|
45 {
|
|
46 _packer.CreatePacker<T> ();
|
|
47 _packer.CreateUnpacker<T> ();
|
|
48 }
|
|
49
|
|
50 #region Generics Pack/Unpack Methods
|
|
51 public byte[] Pack<T> (T o)
|
|
52 {
|
|
53 using (MemoryStream ms = new MemoryStream ()) {
|
|
54 Pack<T> (ms, o);
|
|
55 return ms.ToArray ();
|
|
56 }
|
|
57 }
|
|
58
|
|
59 public void Pack<T> (Stream strm, T o)
|
|
60 {
|
|
61 _packer.CreatePacker<T> () (new MsgPackWriter (strm), o);
|
|
62 }
|
|
63
|
|
64 public T Unpack<T> (byte[] buf)
|
|
65 {
|
|
66 return Unpack<T> (buf, 0, buf.Length);
|
|
67 }
|
|
68
|
|
69 public T Unpack<T> (byte[] buf, int offset, int size)
|
|
70 {
|
|
71 using (MemoryStream ms = new MemoryStream (buf, offset, size)) {
|
|
72 return Unpack<T> (ms);
|
|
73 }
|
|
74 }
|
|
75
|
|
76 public T Unpack<T> (Stream strm)
|
|
77 {
|
|
78 return _packer.CreateUnpacker<T> () (new MsgPackReader (strm));
|
|
79 }
|
|
80 #endregion
|
|
81
|
|
82 #region Non-generics Pack/Unpack Methods
|
|
83 public byte[] Pack (object o)
|
|
84 {
|
|
85 using (MemoryStream ms = new MemoryStream ()) {
|
|
86 Pack (ms, o);
|
|
87 return ms.ToArray ();
|
|
88 }
|
|
89 }
|
|
90
|
|
91 public void Pack (Stream strm, object o)
|
|
92 {
|
|
93 throw new NotImplementedException ();
|
|
94 }
|
|
95
|
|
96 public object Unpack (Type t, byte[] buf)
|
|
97 {
|
|
98 return Unpack (t, buf, 0, buf.Length);
|
|
99 }
|
|
100
|
|
101 public object Unpack (Type t, byte[] buf, int offset, int size)
|
|
102 {
|
|
103 using (MemoryStream ms = new MemoryStream (buf, offset, size)) {
|
|
104 return Unpack (t, ms);
|
|
105 }
|
|
106 }
|
|
107
|
|
108 public object Unpack (Type t, Stream strm)
|
|
109 {
|
|
110 throw new NotImplementedException ();
|
|
111 }
|
|
112 #endregion
|
|
113
|
|
114 #region Compiled Packer Implementations
|
|
115 public abstract class PackerBase
|
|
116 {
|
|
117 Dictionary<Type, Delegate> _packers = new Dictionary<Type, Delegate> ();
|
|
118 Dictionary<Type, Delegate> _unpackers = new Dictionary<Type, Delegate> ();
|
|
119
|
|
120 protected Dictionary<Type, MethodInfo> _packMethods = new Dictionary<Type, MethodInfo> ();
|
|
121 protected Dictionary<Type, MethodInfo> _unpackMethods = new Dictionary<Type, MethodInfo> ();
|
|
122
|
|
123 protected PackerBase ()
|
|
124 {
|
|
125 DefaultPackMethods.Register (_packMethods, _unpackMethods);
|
|
126 }
|
|
127
|
|
128 public Action<MsgPackWriter, T> CreatePacker<T> ()
|
|
129 {
|
|
130 Delegate d;
|
|
131 lock (_packers) {
|
|
132 if (!_packers.TryGetValue (typeof (T), out d)) {
|
|
133 d = CreatePacker_Internal<T> ();
|
|
134 _packers.Add (typeof (T), d);
|
|
135 }
|
|
136 }
|
|
137 return (Action<MsgPackWriter, T>)d;
|
|
138 }
|
|
139
|
|
140 public Func<MsgPackReader, T> CreateUnpacker<T> ()
|
|
141 {
|
|
142 Delegate d;
|
|
143 lock (_unpackers) {
|
|
144 if (!_unpackers.TryGetValue (typeof (T), out d)) {
|
|
145 d = CreateUnpacker_Internal<T> ();
|
|
146 _unpackers.Add (typeof (T), d);
|
|
147 }
|
|
148 }
|
|
149 return (Func<MsgPackReader, T>)d;
|
|
150 }
|
|
151
|
|
152 protected abstract Action<MsgPackWriter, T> CreatePacker_Internal<T> ();
|
|
153 protected abstract Func<MsgPackReader, T> CreateUnpacker_Internal<T> ();
|
|
154 }
|
|
155 public sealed class DynamicMethodPacker : PackerBase
|
|
156 {
|
|
157 private static MethodInfo LookupMemberMappingMethod;
|
|
158 static Dictionary<Type, IDictionary<string, int>> UnpackMemberMappings;
|
|
159
|
|
160 static DynamicMethodPacker ()
|
|
161 {
|
|
162 UnpackMemberMappings = new Dictionary<Type, IDictionary<string, int>> ();
|
|
163 LookupMemberMappingMethod = typeof (DynamicMethodPacker).GetMethod ("LookupMemberMapping", BindingFlags.Static | BindingFlags.NonPublic);
|
|
164 }
|
|
165
|
|
166 public DynamicMethodPacker () : base ()
|
|
167 {
|
|
168 }
|
|
169
|
|
170 protected override Action<MsgPackWriter, T> CreatePacker_Internal<T> ()
|
|
171 {
|
|
172 DynamicMethod dm = CreatePacker (typeof (T), CreatePackDynamicMethod (typeof (T)));
|
|
173 return (Action<MsgPackWriter, T>)dm.CreateDelegate (typeof (Action<MsgPackWriter, T>));
|
|
174 }
|
|
175
|
|
176 protected override Func<MsgPackReader, T> CreateUnpacker_Internal<T> ()
|
|
177 {
|
|
178 DynamicMethod dm = CreateUnpacker (typeof (T), CreateUnpackDynamicMethod (typeof (T)));
|
|
179 return (Func<MsgPackReader, T>)dm.CreateDelegate (typeof (Func<MsgPackReader, T>));
|
|
180 }
|
|
181
|
|
182 DynamicMethod CreatePacker (Type t, DynamicMethod dm)
|
|
183 {
|
|
184 ILGenerator il = dm.GetILGenerator ();
|
|
185 _packMethods.Add (t, dm);
|
|
186 PackILGenerator.EmitPackCode (t, dm, il, LookupMembers, FormatMemberName, LookupPackMethod);
|
|
187 return dm;
|
|
188 }
|
|
189
|
|
190 DynamicMethod CreateUnpacker (Type t, DynamicMethod dm)
|
|
191 {
|
|
192 ILGenerator il = dm.GetILGenerator ();
|
|
193 _unpackMethods.Add (t, dm);
|
|
194 PackILGenerator.EmitUnpackCode (t, dm, il, LookupMembers, FormatMemberName, LookupUnpackMethod,
|
|
195 LookupMemberMapping, LookupMemberMappingMethod);
|
|
196 return dm;
|
|
197 }
|
|
198
|
|
199 static DynamicMethod CreatePackDynamicMethod (Type t)
|
|
200 {
|
|
201 return CreateDynamicMethod (typeof (void), new Type[] {typeof (MsgPackWriter), t});
|
|
202 }
|
|
203
|
|
204 static DynamicMethod CreateUnpackDynamicMethod (Type t)
|
|
205 {
|
|
206 return CreateDynamicMethod (t, new Type[] {typeof (MsgPackReader)});
|
|
207 }
|
|
208
|
|
209 static MemberInfo[] LookupMembers (Type t)
|
|
210 {
|
|
211 BindingFlags baseFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
|
|
212 System.Collections.Generic.List<MemberInfo> list = new System.Collections.Generic.List<MemberInfo> ();
|
|
213 list.AddRange (t.GetFields (baseFlags));
|
|
214 // TODO: Add NonSerialized Attribute Filter ?
|
|
215 return list.ToArray ();
|
|
216 }
|
|
217
|
|
218 MethodInfo LookupPackMethod (Type t)
|
|
219 {
|
|
220 MethodInfo mi;
|
|
221 DynamicMethod dm;
|
|
222 if (_packMethods.TryGetValue (t, out mi))
|
|
223 return mi;
|
|
224 dm = CreatePackDynamicMethod (t);
|
|
225 return CreatePacker (t, dm);
|
|
226 }
|
|
227
|
|
228 MethodInfo LookupUnpackMethod (Type t)
|
|
229 {
|
|
230 MethodInfo mi;
|
|
231 if (_unpackMethods.TryGetValue (t, out mi))
|
|
232 return mi;
|
|
233 DynamicMethod dm = CreateUnpackDynamicMethod (t);
|
|
234 return CreateUnpacker (t, dm);
|
|
235 }
|
|
236
|
|
237 static string FormatMemberName (MemberInfo m)
|
|
238 {
|
|
239 if (m.MemberType != MemberTypes.Field)
|
|
240 return m.Name;
|
|
241
|
|
242 int pos;
|
|
243 string name = m.Name;
|
|
244 if (name[0] == '<' && (pos = name.IndexOf ('>')) > 1)
|
|
245 name = name.Substring (1, pos - 1); // Auto-Property (\<.+\>) <ab>
|
|
246 return name;
|
|
247 }
|
|
248
|
|
249 static int _dynamicMethodIdx = 0;
|
|
250 static DynamicMethod CreateDynamicMethod (Type returnType, Type[] parameterTypes)
|
|
251 {
|
|
252 string name = "_" + Interlocked.Increment (ref _dynamicMethodIdx).ToString ();
|
|
253 return new DynamicMethod (name, returnType, parameterTypes, true);
|
|
254 }
|
|
255
|
|
256 internal static IDictionary<string,int> LookupMemberMapping (Type t)
|
|
257 {
|
|
258 IDictionary<string, int> mapping;
|
|
259 lock (UnpackMemberMappings) {
|
|
260 if (!UnpackMemberMappings.TryGetValue (t, out mapping)) {
|
|
261 mapping = new Dictionary<string, int> ();
|
|
262 UnpackMemberMappings.Add (t, mapping);
|
|
263 }
|
|
264 }
|
|
265 return mapping;
|
|
266 }
|
|
267 }
|
|
268 public sealed class MethodBuilderPacker : PackerBase
|
|
269 {
|
|
270 public const string AssemblyName = "MessagePackInternalAssembly";
|
|
271 static AssemblyName DynamicAsmName;
|
|
272 static AssemblyBuilder DynamicAsmBuilder;
|
|
273 static ModuleBuilder DynamicModuleBuilder;
|
|
274
|
|
275 private static MethodInfo LookupMemberMappingMethod;
|
|
276 static Dictionary<Type, IDictionary<string, int>> UnpackMemberMappings;
|
|
277
|
|
278 static MethodBuilderPacker ()
|
|
279 {
|
|
280 UnpackMemberMappings = new Dictionary<Type, IDictionary<string, int>> ();
|
|
281 LookupMemberMappingMethod = typeof (MethodBuilderPacker).GetMethod ("LookupMemberMapping", BindingFlags.Static | BindingFlags.NonPublic);
|
|
282
|
|
283 DynamicAsmName = new AssemblyName (AssemblyName);
|
|
284 DynamicAsmBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly (DynamicAsmName, AssemblyBuilderAccess.Run);
|
|
285 DynamicModuleBuilder = DynamicAsmBuilder.DefineDynamicModule (DynamicAsmName.Name);
|
|
286 }
|
|
287
|
|
288 public MethodBuilderPacker () : base ()
|
|
289 {
|
|
290 }
|
|
291
|
|
292 protected override Action<MsgPackWriter, T> CreatePacker_Internal<T> ()
|
|
293 {
|
|
294 TypeBuilder tb;
|
|
295 MethodBuilder mb;
|
|
296 CreatePackMethodBuilder (typeof (T), out tb, out mb);
|
|
297 _packMethods.Add (typeof (T), mb);
|
|
298 CreatePacker (typeof (T), mb);
|
|
299 MethodInfo mi = ToCallableMethodInfo (typeof (T), tb, true);
|
|
300 return (Action<MsgPackWriter, T>)Delegate.CreateDelegate (typeof (Action<MsgPackWriter, T>), mi);
|
|
301 }
|
|
302
|
|
303 protected override Func<MsgPackReader, T> CreateUnpacker_Internal<T> ()
|
|
304 {
|
|
305 TypeBuilder tb;
|
|
306 MethodBuilder mb;
|
|
307 CreateUnpackMethodBuilder (typeof (T), out tb, out mb);
|
|
308 _unpackMethods.Add (typeof (T), mb);
|
|
309 CreateUnpacker (typeof (T), mb);
|
|
310 MethodInfo mi = ToCallableMethodInfo (typeof (T), tb, false);
|
|
311 return (Func<MsgPackReader, T>)Delegate.CreateDelegate (typeof (Func<MsgPackReader, T>), mi);
|
|
312 }
|
|
313
|
|
314 void CreatePacker (Type t, MethodBuilder mb)
|
|
315 {
|
|
316 ILGenerator il = mb.GetILGenerator ();
|
|
317 PackILGenerator.EmitPackCode (t, mb, il, LookupMembers, FormatMemberName, LookupPackMethod);
|
|
318 }
|
|
319
|
|
320 void CreateUnpacker (Type t, MethodBuilder mb)
|
|
321 {
|
|
322 ILGenerator il = mb.GetILGenerator ();
|
|
323 PackILGenerator.EmitUnpackCode (t, mb, il, LookupMembers, FormatMemberName, LookupUnpackMethod,
|
|
324 LookupMemberMapping, LookupMemberMappingMethod);
|
|
325 }
|
|
326
|
|
327 MethodInfo ToCallableMethodInfo (Type t, TypeBuilder tb, bool isPacker)
|
|
328 {
|
|
329 Type type = tb.CreateType ();
|
|
330 MethodInfo mi = type.GetMethod (isPacker ? "Pack" : "Unpack", BindingFlags.Static | BindingFlags.Public);
|
|
331 if (isPacker) {
|
|
332 _packMethods[t] = mi;
|
|
333 } else {
|
|
334 _unpackMethods[t] = mi;
|
|
335 }
|
|
336 return mi;
|
|
337 }
|
|
338
|
|
339 MethodInfo LookupPackMethod (Type t)
|
|
340 {
|
|
341 MethodInfo mi;
|
|
342 TypeBuilder tb;
|
|
343 MethodBuilder mb;
|
|
344 if (_packMethods.TryGetValue (t, out mi))
|
|
345 return mi;
|
|
346 CreatePackMethodBuilder (t, out tb, out mb);
|
|
347 _packMethods.Add (t, mb);
|
|
348 CreatePacker (t, mb);
|
|
349 return ToCallableMethodInfo (t, tb, true);
|
|
350 }
|
|
351
|
|
352 MethodInfo LookupUnpackMethod (Type t)
|
|
353 {
|
|
354 MethodInfo mi;
|
|
355 TypeBuilder tb;
|
|
356 MethodBuilder mb;
|
|
357 if (_unpackMethods.TryGetValue (t, out mi))
|
|
358 return mi;
|
|
359 CreateUnpackMethodBuilder (t, out tb, out mb);
|
|
360 _unpackMethods.Add (t, mb);
|
|
361 CreateUnpacker (t, mb);
|
|
362 return ToCallableMethodInfo (t, tb, false);
|
|
363 }
|
|
364
|
|
365 static string FormatMemberName (MemberInfo m)
|
|
366 {
|
|
367 return m.Name;
|
|
368 }
|
|
369
|
|
370 static MemberInfo[] LookupMembers (Type t)
|
|
371 {
|
|
372 BindingFlags baseFlags = BindingFlags.Instance | BindingFlags.Public;
|
|
373 System.Collections.Generic.List<MemberInfo> list = new System.Collections.Generic.List<MemberInfo> ();
|
|
374 list.AddRange (t.GetFields (baseFlags));
|
|
375 // TODO: Add NonSerialized Attribute Filter ?
|
|
376 return list.ToArray ();
|
|
377 }
|
|
378
|
|
379 static void CreatePackMethodBuilder (Type t, out TypeBuilder tb, out MethodBuilder mb)
|
|
380 {
|
|
381 tb = DynamicModuleBuilder.DefineType (t.Name + "PackerType", TypeAttributes.Public);
|
|
382 mb = tb.DefineMethod ("Pack", MethodAttributes.Static | MethodAttributes.Public, typeof (void), new Type[] {typeof (MsgPackWriter), t});
|
|
383 }
|
|
384
|
|
385 static void CreateUnpackMethodBuilder (Type t, out TypeBuilder tb, out MethodBuilder mb)
|
|
386 {
|
|
387 tb = DynamicModuleBuilder.DefineType (t.Name + "UnpackerType", TypeAttributes.Public);
|
|
388 mb = tb.DefineMethod ("Unpack", MethodAttributes.Static | MethodAttributes.Public, t, new Type[] {typeof (MsgPackReader)});
|
|
389 }
|
|
390
|
|
391 internal static IDictionary<string,int> LookupMemberMapping (Type t)
|
|
392 {
|
|
393 IDictionary<string, int> mapping;
|
|
394 lock (UnpackMemberMappings) {
|
|
395 if (!UnpackMemberMappings.TryGetValue (t, out mapping)) {
|
|
396 mapping = new Dictionary<string, int> ();
|
|
397 UnpackMemberMappings.Add (t, mapping);
|
|
398 }
|
|
399 }
|
|
400 return mapping;
|
|
401 }
|
|
402 }
|
|
403 #endregion
|
|
404
|
|
405 #region default pack/unpack methods
|
|
406 internal static class DefaultPackMethods
|
|
407 {
|
|
408 public static void Register (Dictionary<Type, MethodInfo> packMethods, Dictionary<Type, MethodInfo> unpackMethods)
|
|
409 {
|
|
410 RegisterPackMethods (packMethods);
|
|
411 RegisterUnpackMethods (unpackMethods);
|
|
412 }
|
|
413
|
|
414 #region Pack
|
|
415 static void RegisterPackMethods (Dictionary<Type, MethodInfo> packMethods)
|
|
416 {
|
|
417 Type type = typeof (DefaultPackMethods);
|
|
418 MethodInfo[] methods = type.GetMethods (BindingFlags.Static | BindingFlags.NonPublic);
|
|
419 string methodName = "Pack";
|
|
420 for (int i = 0; i < methods.Length; i ++) {
|
|
421 if (!methodName.Equals (methods[i].Name))
|
|
422 continue;
|
|
423 ParameterInfo[] parameters = methods[i].GetParameters ();
|
|
424 if (parameters.Length != 2 || parameters[0].ParameterType != typeof (MsgPackWriter))
|
|
425 continue;
|
|
426 packMethods.Add (parameters[1].ParameterType, methods[i]);
|
|
427 }
|
|
428 }
|
|
429
|
|
430 internal static void Pack (MsgPackWriter writer, string x)
|
|
431 {
|
|
432 if (x == null) {
|
|
433 writer.WriteNil ();
|
|
434 } else {
|
|
435 writer.Write (x, false);
|
|
436 }
|
|
437 }
|
|
438 #endregion
|
|
439
|
|
440 #region Unpack
|
|
441 static void RegisterUnpackMethods (Dictionary<Type, MethodInfo> unpackMethods)
|
|
442 {
|
|
443 BindingFlags flags = BindingFlags.Static | BindingFlags.NonPublic;
|
|
444 Type type = typeof (DefaultPackMethods);
|
|
445 MethodInfo mi = type.GetMethod ("Unpack_Signed", flags);
|
|
446 unpackMethods.Add (typeof (sbyte), mi);
|
|
447 unpackMethods.Add (typeof (short), mi);
|
|
448 unpackMethods.Add (typeof (int), mi);
|
|
449
|
|
450 mi = type.GetMethod ("Unpack_Signed64", flags);
|
|
451 unpackMethods.Add (typeof (long), mi);
|
|
452
|
|
453 mi = type.GetMethod ("Unpack_Unsigned", flags);
|
|
454 unpackMethods.Add (typeof (byte), mi);
|
|
455 unpackMethods.Add (typeof (ushort), mi);
|
|
456 unpackMethods.Add (typeof (char), mi);
|
|
457 unpackMethods.Add (typeof (uint), mi);
|
|
458
|
|
459 mi = type.GetMethod ("Unpack_Unsigned64", flags);
|
|
460 unpackMethods.Add (typeof (ulong), mi);
|
|
461
|
|
462 mi = type.GetMethod ("Unpack_Boolean", flags);
|
|
463 unpackMethods.Add (typeof (bool), mi);
|
|
464
|
|
465 mi = type.GetMethod ("Unpack_Float", flags);
|
|
466 unpackMethods.Add (typeof (float), mi);
|
|
467
|
|
468 mi = type.GetMethod ("Unpack_Double", flags);
|
|
469 unpackMethods.Add (typeof (double), mi);
|
|
470
|
|
471 mi = type.GetMethod ("Unpack_String", flags);
|
|
472 unpackMethods.Add (typeof (string), mi);
|
|
473 }
|
|
474
|
|
475 internal static int Unpack_Signed (MsgPackReader reader)
|
|
476 {
|
|
477 if (!reader.Read () || !reader.IsSigned ())
|
|
478 UnpackFailed ();
|
|
479 return reader.ValueSigned;
|
|
480 }
|
|
481
|
|
482 internal static long Unpack_Signed64 (MsgPackReader reader)
|
|
483 {
|
|
484 if (!reader.Read ())
|
|
485 UnpackFailed ();
|
|
486 if (reader.IsSigned ())
|
|
487 return reader.ValueSigned;
|
|
488 if (reader.IsSigned64 ())
|
|
489 return reader.ValueSigned64;
|
|
490 UnpackFailed ();
|
|
491 return 0; // unused
|
|
492 }
|
|
493
|
|
494 internal static uint Unpack_Unsigned (MsgPackReader reader)
|
|
495 {
|
|
496 if (!reader.Read () || !reader.IsUnsigned ())
|
|
497 UnpackFailed ();
|
|
498 return reader.ValueUnsigned;
|
|
499 }
|
|
500
|
|
501 internal static ulong Unpack_Unsigned64 (MsgPackReader reader)
|
|
502 {
|
|
503 if (!reader.Read ())
|
|
504 UnpackFailed ();
|
|
505 if (reader.IsUnsigned ())
|
|
506 return reader.ValueUnsigned;
|
|
507 if (reader.IsUnsigned64 ())
|
|
508 return reader.ValueUnsigned64;
|
|
509 UnpackFailed ();
|
|
510 return 0; // unused
|
|
511 }
|
|
512
|
|
513 internal static bool Unpack_Boolean (MsgPackReader reader)
|
|
514 {
|
|
515 if (!reader.Read () || !reader.IsBoolean ())
|
|
516 UnpackFailed ();
|
|
517 return reader.ValueBoolean;
|
|
518 }
|
|
519
|
|
520 internal static float Unpack_Float (MsgPackReader reader)
|
|
521 {
|
|
522 if (!reader.Read () || reader.Type != TypePrefixes.Float)
|
|
523 UnpackFailed ();
|
|
524 return reader.ValueFloat;
|
|
525 }
|
|
526
|
|
527 internal static double Unpack_Double (MsgPackReader reader)
|
|
528 {
|
|
529 if (!reader.Read () || reader.Type != TypePrefixes.Double)
|
|
530 UnpackFailed ();
|
|
531 return reader.ValueDouble;
|
|
532 }
|
|
533
|
|
534 internal static string Unpack_String (MsgPackReader reader)
|
|
535 {
|
|
536 if (!reader.Read () || !reader.IsRaw ())
|
|
537 UnpackFailed ();
|
|
538 return reader.ReadRawString ();
|
|
539 }
|
|
540
|
|
541 internal static void UnpackFailed ()
|
|
542 {
|
|
543 throw new FormatException ();
|
|
544 }
|
|
545 #endregion
|
|
546 }
|
|
547 #endregion
|
|
548 }
|
|
549 }
|