Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: msgpack/msgpack
base: master
...
head fork: e-travel/msgpack
compare: master
Checking mergeability… Don't worry, you can still create the pull request.
  • 6 commits
  • 15 files changed
  • 0 commit comments
  • 1 contributor
Commits on Nov 16, 2011
@graffic graffic Add support for properties when looking up members f3a40b1
Commits on Nov 30, 2011
Javier Gonel Packs IDictionary objects
Added the IL generation methods to be able to pack objects from classes
that implement the IDictionary interface.

I've seen code to unpack these things but I haven't tested it.
dbd2085
Javier Gonel Merge branch 'master' of ssh://github.com/e-travel/msgpack
Conflicts:
	csharp/MsgPack/CompiledPacker.cs
c89e517
Commits on Dec 22, 2011
Javier Gonel Tests, Interfaces and some C# types support.
* Some tests for the Dictionary support
* More tests for the Guid as string support
* Added an interface to the Packer to be able to replace it easily for tests.
7db297f
Javier Gonel Guid Unpack support from string 0c61f83
Commits on Jan 06, 2012
Javier Gonel Fixed the dictionary packer IL generator (My fault) 9425657
View
6 .gitignore
@@ -9,7 +9,9 @@ _test
/csharp/MsgPack.suo
/csharp/MsgPack/bin
/csharp/MsgPack/obj
-/csharp/MsgPack/MsgPack.csproj.user
+/csharp/*.user
/csharp/MsgPack.Test/obj
/csharp/MsgPack.Test/bin
-/csharp/MsgPack.Test/MsgPack.Test.csproj.user
+/csharp/*.typemock*
+/csharp/_Resharper.*
+
View
34 csharp/MsgPack.Test/CompiledPackerDynamicMethodTests.cs
@@ -0,0 +1,34 @@
+//
+// Copyright 2011 Kazuki Oikawa
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+using System;
+using System.Collections.Generic;
+using NUnit.Framework;
+using TestA_Class = MsgPack.Test.ObjectPackerTests.TestA_Class;
+using TestB_Class = MsgPack.Test.ObjectPackerTests.TestB_Class;
+
+namespace MsgPack.Test
+{
+ [TestFixture]
+ public class CompiledPackerDynamicMethodTests : DataTypesTestsBase
+ {
+ [TestFixtureSetUp]
+ public void SetUpFixture()
+ {
+ _packer = new CompiledPacker (true);
+ }
+ }
+}
View
47 csharp/MsgPack.Test/CompiledPackerMethodBuilderTests.cs
@@ -0,0 +1,47 @@
+//
+// Copyright 2011 Kazuki Oikawa
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+using NUnit.Framework;
+
+namespace MsgPack.Test
+{
+ [TestFixture]
+ public class CompiledPackerMethodBuilderTests : DataTypesTestsBase
+ {
+ [TestFixtureSetUp]
+ public void SetUpFixture()
+ {
+ _packer = new CompiledPacker(false);
+ }
+
+ [Test]
+ public void TwoPackers_SameType_DoNotConflict()
+ {
+ var packerA = new CompiledPacker(false);
+ var packerB = new CompiledPacker(false);
+ var item = new TestTwoPackers {Test = "TestString"};
+
+ packerA.Pack(item);
+ packerB.Pack(item);
+ }
+
+ public class TestTwoPackers
+ {
+ public string Test;
+ }
+ }
+}
View
13 csharp/MsgPack.Test/CompiledPackerTests.cs
@@ -14,6 +14,8 @@
// limitations under the License.
//
+using System;
+using System.Collections.Generic;
using NUnit.Framework;
using TestA_Class = MsgPack.Test.ObjectPackerTests.TestA_Class;
using TestB_Class = MsgPack.Test.ObjectPackerTests.TestB_Class;
@@ -50,6 +52,17 @@ public void TestB_DynamicMethod ()
TestB (_dynImpl);
}
+ [Test]
+ public void Dictionary_WorksAsMap()
+ {
+ var dict = new Dictionary<string, string> { { "a", "b" }, { "c", "d" } };
+
+ var res = _dynImpl.Pack<Dictionary<string, string>>(dict);
+
+ Assert.AreEqual(new byte[]{130,161,97,161,98,161,99,161,100},res);
+ }
+
+
void TestA (CompiledPacker packer)
{
TestA_Class obj0 = new TestA_Class ();
View
170 csharp/MsgPack.Test/DataTypesTestsBase.cs
@@ -0,0 +1,170 @@
+using System;
+using System.Collections.Generic;
+using NUnit.Framework;
+
+namespace MsgPack.Test
+{
+ [TestFixture]
+ public abstract class DataTypesTestsBase
+ {
+ protected IMsgPacker _packer;
+
+ [Test]
+ public void Unpack_NullString()
+ {
+ var buf = new byte[] {0xa0};
+ var res = _packer.Unpack<string>(buf);
+ Assert.IsNotNull(res);
+ Assert.AreEqual(0,res.Length);
+ }
+
+ [Test]
+ public void Unpack_EmptyString()
+ {
+ var buf = new byte[] { 0xc0 };
+ var res = _packer.Unpack<string>(buf);
+ Assert.IsNull(res);
+ }
+
+ [Test]
+ public void Pack_Guid()
+ {
+ var obj = new TestGuid {MyGuid = Guid.Empty};
+
+ var res = _packer.Pack(obj);
+
+ Assert.AreEqual(new byte[] {
+ 0x81, // Map length 1
+ 0xa6, // Raw length 6
+ 0x4d,0x79,0x47,0x75,0x69,0x64, // MyGuid
+ 0xda,0x00,0x20, // Raw length 32
+ 48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
+ 48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48// Guid.Empty
+ }, res);
+ }
+
+ [Test]
+ public void UnPack_Guid()
+ {
+ var buf = new byte[] {
+ 0x81, // Map length 1
+ 0xa6, // Raw length 6
+ 0x4d,0x79,0x47,0x75,0x69,0x64, // MyGuid
+ 0xda,0x00,0x20, // Raw length 32
+ 48,49,48,50,48,51,48,52,48,48,48,48,48,48,48,48,
+ 48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48// Guid.Empty
+ };
+
+ var res = _packer.Unpack<TestGuid>(buf);
+
+ Assert.AreEqual(Guid.Parse("01020304000000000000000000000000"), res.MyGuid);
+ }
+
+ [Test]
+ public void UnPack_EmptyGuid()
+ {
+ var buf = new byte[] {
+ 0x81, // Map length 1
+ 0xa6, // Raw length 6
+ 0x4d,0x79,0x47,0x75,0x69,0x64, // MyGuid
+ 0xa0 // Raw length 0
+ };
+
+ var res = _packer.Unpack<TestGuid>(buf);
+
+ Assert.AreEqual(Guid.Empty, res.MyGuid);
+ }
+
+ [Test]
+ public void UnPack_NullGuid()
+ {
+ var buf = new byte[] {
+ 0x81, // Map length 1
+ 0xa6, // Raw length 6
+ 0x4d,0x79,0x47,0x75,0x69,0x64, // MyGuid
+ 0xc0 // Raw length 0
+ };
+
+ var res = _packer.Unpack<TestGuid>(buf);
+
+ Assert.AreEqual(Guid.Empty, res.MyGuid);
+ }
+
+
+ [Test]
+ public void Pack_Dictionary_WorksAsMap()
+ {
+ var dict = new Dictionary<string, string> { { "a", "b" }, { "c", "d" } };
+
+ var res = _packer.Pack<Dictionary<string, string>>(dict);
+
+ Assert.AreEqual(new byte[] { 130, 161, 97, 161, 98, 161, 99, 161, 100 }, res);
+ }
+
+ [Test]
+ public void Pack_DictionaryInDictionary_WorksAsMap()
+ {
+ var dict = new Dictionary<string, Dictionary<string, string>> { { "a", new Dictionary<string, string> { { "b", "c" } } } };
+
+ var res = _packer.Pack<Dictionary<string, Dictionary<string, string>>>(dict);
+
+ Assert.AreEqual(new byte[] { 129, 161, 97, 129, 161, 98, 161, 99 }, res);
+ }
+
+ [Test]
+ public void UnPack_EmptyDictionary()
+ {
+ var testData = new byte[] {0x80};
+ var res = _packer.Unpack<Dictionary<string,int>>(testData);
+ Assert.IsNotNull(res);
+ Assert.IsEmpty(res);
+ }
+
+ [Test]
+ public void UnPack_DictionaryInAClass()
+ {
+ var testData = new byte[] { 0x81, 0xa2, 0x4d,0x64,0x80 };
+ var res = _packer.Unpack<TestDictionary1>(testData);
+ Assert.IsNotNull(res);
+ }
+
+ [Test,Ignore]
+ public void Pack_AChar()
+ {
+ char myChar = 'a';
+ var res = _packer.Pack<char>(myChar);
+
+ Assert.AreEqual(new byte[] { 97 }, res);
+ }
+
+ [Test]
+ public void Pack_AChar_InAClass()
+ {
+ var myChar = new TestChar {MyChar = 'a'};
+ var res = _packer.Pack<TestChar>(myChar);
+
+ Assert.AreEqual(new byte[] { 129 // map size 1
+ , 166 // raw size 6
+ , 77, 121, 67, 104, 97, 114, // the string "MyChar"
+ 97 // int 0-127
+ }, res);
+ }
+
+ #region Test Box classes
+ public class TestGuid
+ {
+ public Guid MyGuid { get; set; }
+ }
+
+ public class TestChar
+ {
+ public char MyChar { get; set; }
+ }
+
+ public class TestDictionary1
+ {
+ public Dictionary<string,int> Md { get; set; }
+ }
+ #endregion
+ }
+}
View
3  csharp/MsgPack.Test/MsgPack.Test.csproj
@@ -45,6 +45,9 @@
<Compile Include="AssemblyInfo.cs" />
<Compile Include="BoxingPackerTests.cs" />
<Compile Include="CompiledPackerTests.cs" />
+ <Compile Include="CompiledPackerMethodBuilderTests.cs" />
+ <Compile Include="CompiledPackerDynamicMethodTests.cs" />
+ <Compile Include="DataTypesTestsBase.cs" />
<Compile Include="ObjectPackerTests.cs" />
<Compile Include="ReaderWriterTests.cs" />
</ItemGroup>
View
2  csharp/MsgPack/AssemblyInfo.cs
@@ -24,5 +24,5 @@
[assembly: AssemblyCopyright ("Copyright © 2011 Kazuki Oikawa")]
[assembly: ComVisible (false)]
-[assembly: AssemblyVersion ("0.1.*")]
+[assembly: AssemblyVersion ("0.1.1")]
[assembly: InternalsVisibleTo (MsgPack.CompiledPacker.MethodBuilderPacker.AssemblyName)]
View
51 csharp/MsgPack/BoxingPacker.cs
@@ -22,7 +22,7 @@
namespace MsgPack
{
- public class BoxingPacker
+ public class BoxingPacker : IMsgPacker
{
static Type KeyValuePairDefinitionType;
@@ -31,7 +31,21 @@ static BoxingPacker ()
KeyValuePairDefinitionType = typeof (KeyValuePair<object,object>).GetGenericTypeDefinition ();
}
- public void Pack (Stream strm, object o)
+
+ #region Pack Generic
+ public byte[] Pack<T>(T o)
+ {
+ return Pack((object) o);
+ }
+
+ public void Pack<T>(Stream strm, T o)
+ {
+ Pack(strm, (object) o);
+ }
+ #endregion
+
+ #region Pack
+ public void Pack (Stream strm, object o)
{
MsgPackWriter writer = new MsgPackWriter (strm);
Pack (writer, o);
@@ -44,6 +58,7 @@ public byte[] Pack (object o)
return ms.ToArray ();
}
}
+ #endregion
void Pack (MsgPackWriter writer, object o)
{
@@ -104,7 +119,34 @@ void Pack (MsgPackWriter writer, object o)
}
}
- public object Unpack (Stream strm)
+ #region Unpack generic
+ public T Unpack<T>(byte[] buf)
+ {
+ return (T) Unpack(buf);
+ }
+ public T Unpack<T>(byte[] buf, int offset, int size)
+ {
+ return (T) Unpack(buf, offset, size);
+ }
+ public T Unpack<T>(Stream strm)
+ {
+ return (T) Unpack(strm);
+ }
+
+ #endregion
+
+ #region Unpack
+ // Note: I don't know why the unpack doesn't attach this to an object
+ public object Unpack(Type t, byte[] buf)
+ { throw new NotImplementedException();}
+
+ public object Unpack(Type t, byte[] buf, int offset, int size)
+ {throw new NotImplementedException();}
+
+ public object Unpack(Type t, Stream strm)
+ {throw new NotImplementedException();}
+
+ public object Unpack (Stream strm)
{
MsgPackReader reader = new MsgPackReader (strm);
return Unpack (reader);
@@ -121,8 +163,9 @@ public object Unpack (byte[] buf)
{
return Unpack (buf, 0, buf.Length);
}
+ #endregion
- object Unpack (MsgPackReader reader)
+ object Unpack (MsgPackReader reader)
{
if (!reader.Read ())
throw new FormatException ();
View
78 csharp/MsgPack/CompiledPacker.cs
@@ -13,7 +13,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
-
using System;
using System.Collections.Generic;
using System.IO;
@@ -24,7 +23,7 @@
namespace MsgPack
{
- public class CompiledPacker
+ public class CompiledPacker : IMsgPacker
{
static PackerBase _publicFieldPacker, _allFieldPacker;
PackerBase _packer;
@@ -293,22 +292,39 @@ public MethodBuilderPacker () : base ()
{
TypeBuilder tb;
MethodBuilder mb;
- CreatePackMethodBuilder (typeof (T), out tb, out mb);
- _packMethods.Add (typeof (T), mb);
- CreatePacker (typeof (T), mb);
- MethodInfo mi = ToCallableMethodInfo (typeof (T), tb, true);
- return (Action<MsgPackWriter, T>)Delegate.CreateDelegate (typeof (Action<MsgPackWriter, T>), mi);
+ Type typeofT = typeof (T);
+ var existingType = DynamicModuleBuilder.GetType(typeofT.FullName + "PackerType");
+ MethodInfo existingMethod = null;
+ if (existingType != null)
+ existingMethod = existingType.GetMethod("Pack");
+
+ if (existingMethod == null)
+ {
+ CreatePackMethodBuilder(typeofT, out tb, out mb);
+ CreatePacker(typeofT, mb);
+ existingMethod = ToCallableMethodInfo(typeof(T), tb, true);
+ }
+ if (!_packMethods.ContainsKey(typeofT))
+ {
+ _packMethods.Add(typeofT, existingMethod);
+ }
+
+ return (Action<MsgPackWriter, T>)Delegate.CreateDelegate(typeof(Action<MsgPackWriter, T>), existingMethod);
}
protected override Func<MsgPackReader, T> CreateUnpacker_Internal<T> ()
{
TypeBuilder tb;
MethodBuilder mb;
- CreateUnpackMethodBuilder (typeof (T), out tb, out mb);
- _unpackMethods.Add (typeof (T), mb);
- CreateUnpacker (typeof (T), mb);
- MethodInfo mi = ToCallableMethodInfo (typeof (T), tb, false);
- return (Func<MsgPackReader, T>)Delegate.CreateDelegate (typeof (Func<MsgPackReader, T>), mi);
+ MethodInfo mi;
+ if (!_unpackMethods.TryGetValue(typeof(T), out mi))
+ {
+ CreateUnpackMethodBuilder(typeof (T), out tb, out mb);
+ _unpackMethods.Add(typeof (T), mb);
+ CreateUnpacker(typeof (T), mb);
+ mi = ToCallableMethodInfo(typeof (T), tb, false);
+ }
+ return (Func<MsgPackReader, T>)Delegate.CreateDelegate (typeof (Func<MsgPackReader, T>), mi);
}
void CreatePacker (Type t, MethodBuilder mb)
@@ -372,19 +388,20 @@ static MemberInfo[] LookupMembers (Type t)
BindingFlags baseFlags = BindingFlags.Instance | BindingFlags.Public;
List<MemberInfo> list = new List<MemberInfo> ();
list.AddRange (t.GetFields (baseFlags));
+ list.AddRange( t.GetProperties(baseFlags));
// TODO: Add NonSerialized Attribute Filter ?
return list.ToArray ();
}
static void CreatePackMethodBuilder (Type t, out TypeBuilder tb, out MethodBuilder mb)
{
- tb = DynamicModuleBuilder.DefineType (t.Name + "PackerType", TypeAttributes.Public);
+ tb = DynamicModuleBuilder.DefineType (t.FullName + "PackerType", TypeAttributes.Public);
mb = tb.DefineMethod ("Pack", MethodAttributes.Static | MethodAttributes.Public, typeof (void), new Type[] {typeof (MsgPackWriter), t});
}
static void CreateUnpackMethodBuilder (Type t, out TypeBuilder tb, out MethodBuilder mb)
{
- tb = DynamicModuleBuilder.DefineType (t.Name + "UnpackerType", TypeAttributes.Public);
+ tb = DynamicModuleBuilder.DefineType (t.FullName + "UnpackerType", TypeAttributes.Public);
mb = tb.DefineMethod ("Unpack", MethodAttributes.Static | MethodAttributes.Public, t, new Type[] {typeof (MsgPackReader)});
}
@@ -470,12 +487,19 @@ static void RegisterUnpackMethods (Dictionary<Type, MethodInfo> unpackMethods)
mi = type.GetMethod ("Unpack_String", flags);
unpackMethods.Add (typeof (string), mi);
+
+ mi = type.GetMethod("Unpack_Guid", flags);
+ unpackMethods.Add(typeof(Guid), mi);
}
internal static int Unpack_Signed (MsgPackReader reader)
{
if (!reader.Read () || !reader.IsSigned ())
- UnpackFailed ();
+ {
+ if (reader.Type == TypePrefixes.Nil)
+ return 0;
+ UnpackFailed();
+ }
return reader.ValueSigned;
}
@@ -494,7 +518,11 @@ internal static long Unpack_Signed64 (MsgPackReader reader)
internal static uint Unpack_Unsigned (MsgPackReader reader)
{
if (!reader.Read () || !reader.IsUnsigned ())
- UnpackFailed ();
+ {
+ if (reader.Type == TypePrefixes.Nil)
+ return 0;
+ UnpackFailed();
+ }
return reader.ValueUnsigned;
}
@@ -534,10 +562,26 @@ internal static double Unpack_Double (MsgPackReader reader)
internal static string Unpack_String (MsgPackReader reader)
{
if (!reader.Read () || !reader.IsRaw ())
- UnpackFailed ();
+ {
+ if (reader.Type == TypePrefixes.Nil)
+ return null;
+ UnpackFailed();
+ }
return reader.ReadRawString ();
}
+
+ internal static Guid Unpack_Guid(MsgPackReader reader)
+ {
+ if (!reader.Read() || !reader.IsRaw())
+ {
+ if (reader.Type == TypePrefixes.Nil)
+ return Guid.Empty;
+ UnpackFailed();
+ }
+ return reader.ReadRawGuid();
+ }
+
internal static void UnpackFailed ()
{
throw new FormatException ();
View
194 csharp/MsgPack/Compiler/DictionaryILGenerator.cs
@@ -0,0 +1,194 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Reflection.Emit;
+
+namespace MsgPack.Compiler
+{
+ public static class DictionaryILGenerator
+ {
+ /// <summary>
+ /// Emits IL code to pack a Map based on IDictionary.
+ /// </summary>
+ /// <param name="currentMethod">Current method info.</param>
+ /// <param name="gen">il buffer/generator</param>
+ /// <param name="type">Current type</param>
+ /// <param name="arg_writer">packer object</param>
+ /// <param name="arg_obj">current object</param>
+ /// <param name="lookupPackMethod">dictionary to look for methods</param>
+ public static void EmitPackIL(MethodInfo currentMethod, ILGenerator gen, Type type, Variable arg_writer, Variable arg_obj, Func<Type, MethodInfo> lookupPackMethod)
+ {
+ Type keyType = type.GetGenericArguments()[0];
+ Type valueType = type.GetGenericArguments()[1];
+ Type keyValuePairType = typeof(KeyValuePair<,>).MakeGenericType(keyType, valueType);
+
+ // Preparing Reflection instances
+ MethodInfo getCount = typeof(ICollection<>).MakeGenericType(keyValuePairType).GetMethod(
+ "get_Count",
+ BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
+ null,
+ new Type[]{
+ },
+ null
+ );
+ MethodInfo writeMapHeader = typeof(MsgPackWriter).GetMethod(
+ "WriteMapHeader",
+ BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
+ null,
+ new Type[]{
+ typeof(Int32)
+ },
+ null
+ );
+ MethodInfo getEnumerator = typeof(IEnumerable<>).MakeGenericType(keyValuePairType).GetMethod(
+ "GetEnumerator",
+ BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
+ null,
+ new Type[]{
+ },
+ null
+ );
+ MethodInfo getCurrent = typeof(IEnumerator<>).MakeGenericType(keyValuePairType).GetMethod(
+ "get_Current",
+ BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
+ null,
+ new Type[]{ },
+ null
+ );
+ MethodInfo getKey = keyValuePairType.GetMethod(
+ "get_Key",
+ BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
+ null,
+ new Type[]{ },
+ null
+ );
+
+ MethodInfo getValue = keyValuePairType.GetMethod(
+ "get_Value",
+ BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
+ null,
+ new Type[]{ },
+ null
+ );
+ MethodInfo moveNext = typeof(IEnumerator).GetMethod(
+ "MoveNext",
+ BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
+ null,
+ new Type[]{ },
+ null
+ );
+ MethodInfo dispose = typeof(IDisposable).GetMethod(
+ "Dispose",
+ BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
+ null,
+ new Type[]{ },
+ null
+ );
+
+ // Preparing locals
+ LocalBuilder keyValuepair = gen.DeclareLocal(keyValuePairType);
+ LocalBuilder enumerator = gen.DeclareLocal(typeof(System.Collections.Generic.IEnumerator<>).MakeGenericType(keyValuePairType));
+ Variable localValue = Variable.CreateLocal(gen.DeclareLocal(valueType));
+
+ // Preparing labels
+ Label getNext = gen.DefineLabel();
+ Label work = gen.DefineLabel();
+ Label end = gen.DefineLabel();
+ Label endFinally = gen.DefineLabel();
+
+ // Writing body
+ gen.Emit(OpCodes.Ldarg_0);
+ gen.Emit(OpCodes.Ldarg_1);
+ gen.Emit(OpCodes.Callvirt, getCount);
+ gen.Emit(OpCodes.Callvirt, writeMapHeader);
+ gen.Emit(OpCodes.Ldarg_1);
+ gen.Emit(OpCodes.Callvirt, getEnumerator);
+ gen.Emit(OpCodes.Stloc_1);
+ gen.BeginExceptionBlock();
+ gen.Emit(OpCodes.Br_S, getNext);
+ gen.MarkLabel(work);
+ gen.Emit(OpCodes.Ldloc_1);
+ gen.Emit(OpCodes.Callvirt, getCurrent);
+ gen.Emit(OpCodes.Stloc_0);
+ gen.Emit(OpCodes.Ldarg_0);
+ gen.Emit(OpCodes.Ldloca_S, 0);
+ gen.Emit(OpCodes.Call, getKey);
+ EmitPack(gen, keyType, type, currentMethod, lookupPackMethod);
+ gen.Emit(OpCodes.Ldarg_0);
+ gen.Emit(OpCodes.Ldloca_S, 0);
+ gen.Emit(OpCodes.Call, getValue);
+ EmitPack(gen, valueType, type, currentMethod, lookupPackMethod);
+ gen.MarkLabel(getNext);
+ gen.Emit(OpCodes.Ldloc_1);
+ gen.Emit(OpCodes.Callvirt, moveNext);
+ gen.Emit(OpCodes.Brtrue_S, work);
+ gen.Emit(OpCodes.Leave_S, end);
+ gen.BeginFinallyBlock();
+ gen.Emit(OpCodes.Ldloc_1);
+ gen.Emit(OpCodes.Brfalse_S, endFinally);
+ gen.Emit(OpCodes.Ldloc_1);
+ gen.Emit(OpCodes.Callvirt, dispose);
+ gen.MarkLabel(endFinally);
+ gen.Emit(OpCodes.Endfinally);
+ gen.EndExceptionBlock();
+ gen.MarkLabel(end);
+ gen.Emit(OpCodes.Ret); // <- Yep, I know there is a Ret in the calling function.
+ // finished
+ }
+
+ public static void EmitUnpackIL(Type mapType, MethodInfo mi, ILGenerator il,
+ Func<Type, MemberInfo[]> targetMemberSelector,
+ Func<MemberInfo, string> memberNameFormatter,
+ Func<Type, MethodInfo> lookupUnpackMethod)
+ {
+
+ // References
+ var failedMethod = typeof(PackILGenerator).GetMethod("UnpackFailed", BindingFlags.Static | BindingFlags.NonPublic);
+ // Variables
+ var obj = Variable.CreateLocal(il.DeclareLocal(mapType));
+ var msgpackReader = Variable.CreateArg(0);
+ var var_type = Variable.CreateLocal(il.DeclareLocal(typeof(Type)));
+ var num_of_fields = Variable.CreateLocal(il.DeclareLocal(typeof(int)));
+
+ PackILGenerator.EmitUnpackReadAndTypeCheckCode(il, msgpackReader, typeof(MsgPackReader).GetMethod("IsMap"), failedMethod, true);
+
+ // num_of_fields = (int)reader.Length
+ il.EmitLd(msgpackReader);
+ il.Emit(OpCodes.Call, typeof(MsgPackReader).GetProperty("Length").GetGetMethod());
+ il.EmitSt(num_of_fields);
+
+ // mapType
+ il.EmitLd(num_of_fields);
+ il.Emit(OpCodes.Newobj, mapType.GetConstructor(new Type[] { typeof(int) }));
+ il.EmitSt(obj);
+
+ // Problems with this: It only reads empty dictionaries.
+
+ // return
+ il.EmitLd(obj);
+ il.Emit(OpCodes.Ret);
+ }
+
+ public static void EmitPack(ILGenerator gen, Type type, Type currentType, MethodInfo currentMethod, Func<Type, MethodInfo> lookupPackMethod)
+ {
+ MethodInfo packerMethod=null;
+ if (type.IsPrimitive || type == typeof(Guid))
+ {
+ packerMethod = typeof(MsgPackWriter).GetMethod("Write", new Type[] { type });
+ }
+ if(packerMethod == null)
+ {
+ if (currentType == type)
+ {
+ packerMethod = currentMethod;
+ }
+ else
+ {
+ packerMethod = lookupPackMethod(type);
+ }
+ }
+ gen.Emit(OpCodes.Call, packerMethod);
+ }
+ }
+}
View
89 csharp/MsgPack/Compiler/PackILGenerator.cs
@@ -15,6 +15,7 @@
//
using System;
+using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
@@ -30,12 +31,13 @@ static class PackILGenerator
Func<MemberInfo,string> memberNameFormatter,
Func<Type, MethodInfo> lookupPackMethod)
{
- if (type.IsPrimitive || type.IsInterface)
+ if ((type.IsPrimitive || type.IsInterface) && !type.IsMap())
throw new NotSupportedException ();
Variable arg_writer = Variable.CreateArg (0);
Variable arg_obj = Variable.CreateArg (1);
- Variable local_i = Variable.CreateLocal (il.DeclareLocal (typeof (int)));
+
+
if (!type.IsValueType) { // null check
Label notNullLabel = il.DefineLabel ();
@@ -47,33 +49,40 @@ static class PackILGenerator
il.MarkLabel (notNullLabel);
}
- if (type.IsArray) {
- EmitPackArrayCode (mi, il, type, arg_writer, arg_obj, local_i, lookupPackMethod);
- goto FinallyProcess;
- }
-
- // MsgPackWriter.WriteMapHeader
- MemberInfo[] members = targetMemberSelector (type);
- il.EmitLd (arg_writer);
- il.EmitLdc (members.Length);
- il.Emit (OpCodes.Callvirt, typeof (MsgPackWriter).GetMethod("WriteMapHeader", new Type[]{typeof (int)}));
-
- for (int i = 0; i < members.Length; i ++) {
- MemberInfo m = members[i];
- Type mt = m.GetMemberType ();
-
- // write field-name
- il.EmitLd (arg_writer);
- il.EmitLdstr (memberNameFormatter (m));
- il.EmitLd_True ();
- il.Emit (OpCodes.Call, typeof (MsgPackWriter).GetMethod("Write", new Type[]{typeof (string), typeof (bool)}));
-
- // write value
- EmitPackMemberValueCode (mt, il, arg_writer, arg_obj, m, null, type, mi, lookupPackMethod);
- }
+ if (type.IsArray)
+ {
+ EmitPackArrayCode(mi, il, type, arg_writer, arg_obj, Variable.CreateLocal(il.DeclareLocal(typeof(int))), lookupPackMethod);
+ goto FinallyProcess;
+ }
+ if (type.IsMap())
+ {
+ //EmitPackDictCode(mi, il, type, arg_writer, arg_obj, lookupPackMethod);
+ Compiler.DictionaryILGenerator.EmitPackIL(mi, il, type, arg_writer, arg_obj, lookupPackMethod);
+ goto FinallyProcess;
+ }
+ // MsgPackWriter.WriteMapHeader
+ MemberInfo[] members = targetMemberSelector(type);
+ il.EmitLd(arg_writer);
+ il.EmitLdc(members.Length);
+ il.Emit(OpCodes.Callvirt, typeof(MsgPackWriter).GetMethod("WriteMapHeader", new Type[] { typeof(int) }));
+
+ for (int i = 0; i < members.Length; i++)
+ {
+ MemberInfo m = members[i];
+ Type mt = m.GetMemberType();
+
+ // write field-name
+ il.EmitLd(arg_writer);
+ il.EmitLdstr(memberNameFormatter(m));
+ il.EmitLd_True();
+ il.Emit(OpCodes.Call, typeof(MsgPackWriter).GetMethod("Write", new Type[] { typeof(string), typeof(bool) }));
+
+ // write value
+ EmitPackMemberValueCode(mt, il, arg_writer, arg_obj, m, null, type, mi, lookupPackMethod);
+ }
FinallyProcess:
- il.Emit (OpCodes.Ret);
+ il.Emit (OpCodes.Ret);
}
static void EmitPackArrayCode (MethodInfo mi, ILGenerator il, Type t, Variable var_writer, Variable var_obj, Variable var_loop, Func<Type, MethodInfo> lookupPackMethod)
@@ -116,7 +125,7 @@ static void EmitPackArrayCode (MethodInfo mi, ILGenerator il, Type t, Variable v
/// <param name="m">(optional)</param>
/// <param name="elementIdx">(optional)</param>
- static void EmitPackMemberValueCode (Type type, ILGenerator il, Variable var_writer, Variable var_obj,
+ public static void EmitPackMemberValueCode (Type type, ILGenerator il, Variable var_writer, Variable var_obj,
MemberInfo m, Variable elementIdx, Type currentType, MethodInfo currentMethod, Func<Type, MethodInfo> lookupPackMethod)
{
MethodInfo mi;
@@ -127,7 +136,7 @@ static void EmitPackArrayCode (MethodInfo mi, ILGenerator il, Type t, Variable v
il.EmitLd (elementIdx);
il.Emit (OpCodes.Ldelem, type);
}
- if (type.IsPrimitive) {
+ if (type.IsPrimitive || type == typeof(Guid)) {
mi = typeof(MsgPackWriter).GetMethod("Write", new Type[]{type});
} else {
if (currentType == type) {
@@ -150,11 +159,18 @@ static void EmitPackArrayCode (MethodInfo mi, ILGenerator il, Type t, Variable v
{
if (type.IsArray) {
EmitUnpackArrayCode (type, mi, il, targetMemberSelector, memberNameFormatter, lookupUnpackMethod);
- } else {
+ }
+ else if (type.IsMap())
+ {
+ DictionaryILGenerator.EmitUnpackIL(type, mi, il, targetMemberSelector, memberNameFormatter, lookupUnpackMethod);
+ }
+ else {
EmitUnpackMapCode (type, mi, il, targetMemberSelector, memberNameFormatter, lookupUnpackMethod, lookupMemberMapping, lookupMemberMappingMethod);
}
}
+
+
static void EmitUnpackMapCode (Type type, MethodInfo mi, ILGenerator il,
Func<Type,MemberInfo[]> targetMemberSelector,
Func<MemberInfo,string> memberNameFormatter,
@@ -337,7 +353,7 @@ static void EmitPackArrayCode (MethodInfo mi, ILGenerator il, Type t, Variable v
il.Emit (OpCodes.Ret);
}
- static void EmitUnpackReadAndTypeCheckCode (ILGenerator il, Variable msgpackReader, MethodInfo typeCheckMethod, MethodInfo failedMethod, bool nullCheckAndReturn)
+ public static void EmitUnpackReadAndTypeCheckCode (ILGenerator il, Variable msgpackReader, MethodInfo typeCheckMethod, MethodInfo failedMethod, bool nullCheckAndReturn)
{
Label lblFailed = il.DefineLabel ();
Label lblNullReturn = nullCheckAndReturn ? il.DefineLabel () : default(Label);
@@ -381,6 +397,17 @@ static Type GetMemberType (this MemberInfo mi)
return ((PropertyInfo)mi).PropertyType;
throw new ArgumentException ();
}
+
+ /// <summary>
+ /// Checks if a type is elegible for "Map" serialization.
+ /// </summary>
+ /// <param name="type"></param>
+ /// <returns></returns>
+ static bool IsMap(this Type type)
+ {
+ // Checks we can assign it to an IDictionary
+ return typeof (IDictionary).IsAssignableFrom(type);
+ }
#endregion
}
}
View
30 csharp/MsgPack/IMsgPacker.cs
@@ -0,0 +1,30 @@
+using System;
+using System.IO;
+
+namespace MsgPack
+{
+ public interface IMsgPacker
+ {
+ #region Pack Generic
+ byte[] Pack<T> (T o);
+ void Pack<T> (Stream strm, T o);
+ #endregion
+
+ #region Pack
+ byte[] Pack(object o);
+ void Pack(Stream strm, object o);
+ #endregion
+
+ #region Unpack generic
+ T Unpack<T> (byte[] buf);
+ T Unpack<T> (byte[] buf, int offset, int size);
+ T Unpack<T> (Stream strm);
+ #endregion
+
+ #region Unpack
+ object Unpack (Type t, byte[] buf);
+ object Unpack (Type t, byte[] buf, int offset, int size);
+ object Unpack (Type t, Stream strm);
+ #endregion
+ }
+}
View
2  csharp/MsgPack/MsgPack.csproj
@@ -43,8 +43,10 @@
<Compile Include="CompiledPacker.cs" />
<Compile Include="Compiler\EmitExtensions.cs" />
<Compile Include="Compiler\PackILGenerator.cs" />
+ <Compile Include="Compiler\DictionaryILGenerator.cs" />
<Compile Include="Compiler\Variable.cs" />
<Compile Include="Compiler\VariableType.cs" />
+ <Compile Include="IMsgPacker.cs" />
<Compile Include="MsgPackReader.cs" />
<Compile Include="MsgPackWriter.cs" />
<Compile Include="ObjectPacker.cs" />
View
8 csharp/MsgPack/MsgPackReader.cs
@@ -254,5 +254,13 @@ public unsafe string ReadRawString (byte[] buf)
throw new FormatException ();
return _encoding.GetString (tmp);
}
+
+ public Guid ReadRawGuid()
+ {
+ var guidAsString = ReadRawString();
+ return String.IsNullOrWhiteSpace(guidAsString)
+ ? Guid.Empty
+ : Guid.ParseExact(guidAsString,"N");
+ }
}
}
View
8 csharp/MsgPack/MsgPackWriter.cs
@@ -20,7 +20,8 @@
namespace MsgPack
{
- public class MsgPackWriter
+ // This class is sealed to use Call instead of Callvirt
+ public sealed class MsgPackWriter
{
Stream _strm;
Encoding _encoding = Encoding.UTF8;
@@ -33,6 +34,11 @@ public MsgPackWriter (Stream strm)
_strm = strm;
}
+ public void Write(Guid x)
+ {
+ Write(x.ToString("N"));
+ }
+
public void Write (byte x)
{
if (x < 128) {

No commit comments for this range

Something went wrong with that request. Please try again.