// // 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; using System.Collections.Generic; using System.IO; using System.Reflection; namespace MsgPack { public class BoxingPacker { static Type KeyValuePairDefinitionType; static BoxingPacker () { KeyValuePairDefinitionType = typeof (KeyValuePair).GetGenericTypeDefinition (); } public void Pack (Stream strm, object o) { MsgPackWriter writer = new MsgPackWriter (strm); Pack (writer, o); } public byte[] Pack (object o) { using (MemoryStream ms = new MemoryStream ()) { Pack (ms, o); return ms.ToArray (); } } void Pack (MsgPackWriter writer, object o) { if (o == null) { writer.WriteNil (); return; } Type t = o.GetType (); if (t.IsPrimitive) { if (t.Equals (typeof (int))) writer.Write ((int)o); else if (t.Equals (typeof (uint))) writer.Write ((uint)o); else if (t.Equals (typeof (float))) writer.Write ((float)o); else if (t.Equals (typeof (double))) writer.Write ((double)o); else if (t.Equals (typeof (long))) writer.Write ((long)o); else if (t.Equals (typeof (ulong))) writer.Write ((ulong)o); else if (t.Equals (typeof (bool))) writer.Write ((bool)o); else if (t.Equals (typeof (byte))) writer.Write ((byte)o); else if (t.Equals (typeof (sbyte))) writer.Write ((sbyte)o); else if (t.Equals (typeof (short))) writer.Write ((short)o); else if (t.Equals (typeof (ushort))) writer.Write ((ushort)o); else throw new NotSupportedException (); // char? return; } IDictionary dic = o as IDictionary; if (dic != null) { writer.WriteMapHeader (dic.Count); foreach (System.Collections.DictionaryEntry e in dic) { Pack (writer, e.Key); Pack (writer, e.Value); } return; } if (t.IsArray) { Array ary = (Array)o; Type et = t.GetElementType (); // KeyValuePair[] (Map Type) if (et.IsGenericType && et.GetGenericTypeDefinition ().Equals (KeyValuePairDefinitionType)) { PropertyInfo propKey = et.GetProperty ("Key"); PropertyInfo propValue = et.GetProperty ("Value"); writer.WriteMapHeader (ary.Length); for (int i = 0; i < ary.Length; i ++) { object e = ary.GetValue (i); Pack (writer, propKey.GetValue (e, null)); Pack (writer, propValue.GetValue (e, null)); } return; } // Array writer.WriteArrayHeader (ary.Length); for (int i = 0; i < ary.Length; i ++) Pack (writer, ary.GetValue (i)); return; } } public object Unpack (Stream strm) { MsgPackReader reader = new MsgPackReader (strm); return Unpack (reader); } public object Unpack (byte[] buf, int offset, int size) { using (MemoryStream ms = new MemoryStream (buf, offset, size)) { return Unpack (ms); } } public object Unpack (byte[] buf) { return Unpack (buf, 0, buf.Length); } object Unpack (MsgPackReader reader) { if (!reader.Read ()) throw new FormatException (); switch (reader.Type) { case TypePrefixes.PositiveFixNum: case TypePrefixes.NegativeFixNum: case TypePrefixes.Int8: case TypePrefixes.Int16: case TypePrefixes.Int32: return reader.ValueSigned; case TypePrefixes.Int64: return reader.ValueSigned64; case TypePrefixes.UInt8: case TypePrefixes.UInt16: case TypePrefixes.UInt32: return reader.ValueUnsigned; case TypePrefixes.UInt64: return reader.ValueUnsigned64; case TypePrefixes.True: return true; case TypePrefixes.False: return false; case TypePrefixes.Float: return reader.ValueFloat; case TypePrefixes.Double: return reader.ValueDouble; case TypePrefixes.Nil: return null; case TypePrefixes.FixRaw: case TypePrefixes.Raw16: case TypePrefixes.Raw32: byte[] raw = new byte[reader.Length]; reader.ReadValueRaw (raw, 0, raw.Length); return raw; case TypePrefixes.FixArray: case TypePrefixes.Array16: case TypePrefixes.Array32: object[] ary = new object[reader.Length]; for (int i = 0; i < ary.Length; i ++) ary[i] = Unpack (reader); return ary; case TypePrefixes.FixMap: case TypePrefixes.Map16: case TypePrefixes.Map32: IDictionary dic = new Dictionary ((int)reader.Length); int count = (int)reader.Length; for (int i = 0; i < count; i ++) { object k = Unpack (reader); object v = Unpack (reader); dic.Add (k, v); } return dic; default: throw new FormatException (); } } } }