comparison Main/jungle-main/persistent/msgpack/src/CompiledPacker.cs @ 20:1f99e150f336

fix folder and add Object Mapper.
author Kazuma Takeda
date Thu, 15 Dec 2016 22:52:48 +0900
parents
children
comparison
equal deleted inserted replaced
19:0865819106cf 20:1f99e150f336
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 }