private static object _deserialize(Type T, Type container, byte[] bytes, out int amountread, bool sizeknown)
        {
            if (bytes.Length == 0 && !WHAT_IS_HAPPENING)
            {
//                Console.WriteLine("Deserializing empty array?");
                amountread = 0;
                return(null);
            }
            object thestructure = null;

            if (T.FullName.Contains("System.") && !T.IsCOMObject && !T.IsArray && T != typeof(string))
            {
                thestructure = new object();
                int    size = Marshal.SizeOf(T);
                IntPtr mem  = IntPtr.Zero;
                if (bytes.Length != 0)
                {
                    mem = Marshal.AllocHGlobal(size);
                    Marshal.Copy(bytes, 0, mem, size);
                }
                amountread = size;
                if (WHAT_IS_HAPPENING)
                {
                    /*
                     * Console.WriteLine("//deserialize: " + T.FullName);
                     * /*Console.WriteLine(string.Format(@"    $A = new {0}();
                     * IntPtr $B = Marshal.AllocHGlobal({1})
                     * Marshal.Copy(bytes, 0, $B, {1});
                     * $A = Marshal.PtrToStructure($B, typeof({0}));
                     * ", T.FullName, Marshal.SizeOf(T)));*/
                }
                return(mem != IntPtr.Zero ? Marshal.PtrToStructure(mem, T) : null);
            }
            IRosMessage MSG;
            int         startingpos = 0, currpos = 0;

            /*if (container==null)
             * currpos = 4;*/
            MsgTypes MT = MsgTypes.Unknown;

            FieldInfo[] infos = GetFields(T, ref thestructure, out MSG);
            if (MSG != null)
            {
                MT = MSG.msgtype;
            }
            startingpos = currpos;

            int currinfo = 0;

            while ((currpos < bytes.Length || WHAT_IS_HAPPENING) && currinfo < infos.Length)
            {
                // Console.WriteLine(infos[currinfo].Name + "(" + currpos + "/" + bytes.Length + ")");
                Type type = GetType(infos[currinfo].FieldType.FullName);
                //Console.WriteLine("GetType returned: " + type.FullName);
                Type     realtype = infos[currinfo].FieldType;
                MsgTypes msgtype  = GetMessageType(type);

                bool knownpiecelength = IsSizeKnown(realtype, true) && MSG.Fields != null && !MSG.Fields[infos[currinfo].Name].IsArray || MSG.Fields[infos[currinfo].Name].Length != -1;
                if (knownpiecelength)
                {
                    if (infos[currinfo].FieldType.IsArray && msgtype == MsgTypes.std_msgs__Byte)
                    {
                        Array vals = (infos[currinfo].GetValue(thestructure) as Array);
                        if (vals != null)
                        {
                            int    num   = vals.Length;
                            byte[] PWNED = new byte[num];
                            Array.Copy(bytes, currpos, PWNED, 0, num);
                            currpos += num;
                            infos[currinfo].SetValue(thestructure, PWNED);
                        }
                    }
                    else if (infos[currinfo].FieldType.IsArray && msgtype != MsgTypes.std_msgs__String)
                    //must have length defined, or else knownpiecelength would be false... so look it up in the dict!
                    {
                        Type TT = GetType(infos[currinfo].FieldType.GetElementType().FullName);
                        if (TT.IsArray)
                        {
                            throw new Exception("ERIC, YOU NEED TO MAKE DESERIALIZATION RECURSE!!!");
                        }
                        Array vals = (infos[currinfo].GetValue(thestructure) as Array);
                        if (vals != null)
                        {
                            for (int i = 0; i < vals.Length; i++)
                            {
                                MsgTypes mt   = GetMessageType(TT);
                                int      leng = 0;
                                Type     et   = realtype.GetElementType();
                                if (mt == MsgTypes.Unknown)
                                {
                                    leng = Marshal.SizeOf(et);
                                }
                                if (leng == 0)
                                {
                                    leng = Marshal.SizeOf(vals.GetValue(i));
                                }
                                if (leng == 0)
                                {
                                    throw new Exception("LENGTH ENUMERATION FAIL IN DESERIALIZE!");
                                }
                                if (leng + currpos <= bytes.Length)
                                {
                                    IntPtr pIP = Marshal.AllocHGlobal(leng);
                                    Marshal.Copy(bytes, currpos, pIP, leng);
                                    object o = Marshal.PtrToStructure(pIP, TT);
                                    vals.SetValue(o, i);
                                }
                                else
                                {
                                    vals.SetValue(null, i);
                                }
                                currpos += leng;
                            }
                        }
                        infos[currinfo].SetValue(thestructure, vals);
                    }
                    else
                    {
                        if (type.FullName != null && type.FullName.Contains("Message"))
                        {
                            if (GetMessageType(realtype) == MsgTypes.std_msgs__Time || GetMessageType(realtype) == MsgTypes.std_msgs__Duration || infos[currinfo].FieldType == typeof(TimeData))
                            {
                                TimeData td;
                                if (currpos + 8 <= bytes.Length)
                                {
                                    uint u1 = BitConverter.ToUInt32(bytes, currpos);
                                    uint u2 = BitConverter.ToUInt32(bytes, currpos + 4);
                                    td = new TimeData(u1, u2);
                                }
                                else
                                {
                                    td = new TimeData(0, 0);
                                }
                                currpos += 8;
                                if (infos[currinfo].FieldType == typeof(TimeData))
                                {
                                    infos[currinfo].SetValue(thestructure, td);
                                }
                                else if (GetMessageType(realtype) == MsgTypes.std_msgs__Time)
                                {
                                    infos[currinfo].SetValue(thestructure, (object)new std_msgs.Time(td));
                                }
                                else
                                {
                                    infos[currinfo].SetValue(thestructure, (object)new std_msgs.Duration(td));
                                }
                            }
                            else
                            {
                                byte[] piece = new byte[bytes.Length != 0 ? bytes.Length - currpos : 0];
                                if (bytes.Length != 0)
                                {
                                    Array.Copy(bytes, currpos, piece, 0, piece.Length);
                                }
                                int    len = 0;
                                object obj = _deserialize(realtype, T, piece, out len,
                                                          IsSizeKnown(realtype, true));
                                //if ((int)(infos[currinfo].Attributes & FieldAttributes.InitOnly) != 0)
                                infos[currinfo].SetValue(thestructure, obj);
                                currpos += len;
                            }
                        }
                        else
                        {
                            int    len = Marshal.SizeOf(infos[currinfo].GetValue(thestructure));
                            IntPtr pIP = Marshal.AllocHGlobal(len);
                            object obj = null;
                            if (currpos + len <= bytes.Length)
                            {
                                Marshal.Copy(bytes, currpos, pIP, len);
                                obj = Marshal.PtrToStructure(pIP, infos[currinfo].FieldType);
                            }
                            infos[currinfo].SetValue(thestructure, obj);
                            currpos += len;
                        }
                    }
                }
                else
                {
                    Type ft = realtype;
                    if (ft.IsArray)
                    {
                        Type  TT       = ft.GetElementType();
                        Array val      = infos[currinfo].GetValue(thestructure) as Array;
                        int   chunklen = 0;
                        if (val == null)
                        {
                            if (currpos + 4 <= bytes.Length)
                            {
                                chunklen = BitConverter.ToInt32(bytes, currpos);
                                currpos += 4;
                                val      = Array.CreateInstance(TT, chunklen);
                            }
                            else
                            {
                                currpos += 4;
                                val      = Array.CreateInstance(TT, 0);
                            }
                        }
                        else
                        {
                            chunklen = val.Length;
                        }
                        if (TT == null)
                        {
                            throw new Exception("LENGTHLESS ARRAY FAIL -- ELEMENT TYPE IS NULL!");
                        }
                        if (TT == typeof(string) || TT.FullName.Contains("Message."))
                        {
                            throw new Exception("NOT YET, YOUNG PATAWAN");
                        }
                        MsgTypes mt = GetMessageType(TT);
                        if (mt == MsgTypes.std_msgs__Byte)
                        {
                            int    num   = val.Length;
                            byte[] PWNED = new byte[num];
                            if (currpos + num <= bytes.Length)
                            {
                                Array.Copy(bytes, currpos, PWNED, 0, num);
                            }
                            currpos += num;
                            infos[currinfo].SetValue(thestructure, PWNED);
                        }
                        else if (TT.FullName != null && TT.FullName.Contains("Message"))
                        {
                            for (int i = 0; i < chunklen; i++)
                            {
                                byte[] chunk = new byte[bytes.Length - currpos];
                                Array.Copy(bytes, currpos, chunk, 0, chunk.Length);
                                int    len  = 0;
                                object data = _deserialize(TT, T, chunk, out len,
                                                           IsSizeKnown(TT, false));
                                val.SetValue(data, i);
                                currpos += len;
                            }
                            infos[currinfo].SetValue(thestructure, val);
                        }
                        else
                        {
                            int    len = Marshal.SizeOf(TT);
                            IntPtr pIP = IntPtr.Zero;
                            if (currpos + len * chunklen <= bytes.Length)
                            {
                                pIP = Marshal.AllocHGlobal(len * chunklen);
                                Marshal.Copy(bytes, currpos, pIP, len * chunklen);
                            }
                            object o = null;
                            for (int i = 0; i < chunklen * len; i += len)
                            {
                                if (pIP != IntPtr.Zero)
                                {
                                    o = Marshal.PtrToStructure(pIP, TT);
                                }
                                val.SetValue(o, i / len);
                                if (pIP != IntPtr.Zero)
                                {
                                    pIP = new IntPtr(pIP.ToInt32() + len);
                                }
                            }
                            infos[currinfo].SetValue(thestructure, val);
                            currpos += chunklen * len;
                        }
                    }
                    else
                    {
                        if (ft.FullName != null && ft.FullName.Contains("Message"))
                        {
                            IRosMessage msg       = (IRosMessage)Activator.CreateInstance(ft);
                            Type        t         = GetType(msg.GetType().FullName);
                            bool        knownsize = IsSizeKnown(t, false) && MSG.Fields != null && !MSG.Fields[infos[currinfo].Name].IsArray || MSG.Fields[infos[currinfo].Name].Length != -1;
                            if (!knownsize && t.GetField("data").FieldType == typeof(string))
                            {
                                int len = -4;
                                if (currpos + 4 <= bytes.Length)
                                {
                                    len = BitConverter.ToInt32(bytes, currpos);
                                }
                                byte[] smallerpiece = new byte[len + 4];
                                if (currpos + 4 <= bytes.Length)
                                {
                                    Array.Copy(bytes, currpos, smallerpiece, 0, smallerpiece.Length);
                                }
                                int dontcare = 0;
                                msg = _deserialize(t, T, smallerpiece, out dontcare, false) as IRosMessage;
                                if (bytes.Length != 0 && dontcare != len + 4)
                                {
                                    throw new Exception("WTF?!");
                                }
                                infos[currinfo].SetValue(thestructure, msg);
                                currpos += len + 4;
                            }
                            else // if (!knownsize)
                            {
                                byte[] smallerpiece = new byte[bytes.Length != 0 ? bytes.Length - currpos : 0];
                                if (bytes.Length != 0)
                                {
                                    Array.Copy(bytes, currpos, smallerpiece, 0, smallerpiece.Length);
                                }
                                int len = 0;
                                msg = _deserialize(t, T, smallerpiece, out len, knownsize) as IRosMessage;
                                infos[currinfo].SetValue(thestructure, msg);
                                currpos += len;
                            }

                            /*else
                             * {
                             *  throw new Exception("THIS BROKE SOMEHOW! FIX IT!");
                             * }*/
                        }
                        else
                        {
                            if (infos[currinfo].FieldType == typeof(string))
                            {
                                int len = 0;
                                if (currpos + 4 <= bytes.Length)
                                {
                                    len = BitConverter.ToInt32(bytes, currpos);
                                }
                                byte[] piece = new byte[len];
                                currpos += 4;
                                if (currpos + len <= bytes.Length)
                                {
                                    Array.Copy(bytes, currpos, piece, 0, len);
                                }
                                string str = Encoding.ASCII.GetString(piece);
                                infos[currinfo].SetValue(thestructure, str);
                                currpos += len;
                            }
                            else
                            {
                                //Console.WriteLine("ZOMG HANDLE: " + infos[currinfo].FieldType.FullName);
                                amountread = currpos - startingpos;
                                return(thestructure);
                            }
                        }
                    }
                }
                currinfo++;
            }
            amountread = currpos - startingpos;
            return(thestructure);
        }
 private void RandomizeField(Type T, ref object target, int hardcodedarraylength=-1)
 {
     if (!T.IsArray)
     {
         if (T != typeof(TimeData) && T.Namespace.Contains("Message"))
         {
             //Create a new object of the same type as target?
             object msg = Activator.CreateInstance(T);
             FieldInfo[] infos = GetFields(T, ref target);
             if (msg == null)
             {
                 GetFields(T, ref target);
                 throw new Exception("SOMETHING AIN'T RIGHT");
             }
             foreach (FieldInfo info in infos)
             {
                 if (info.Name.Contains("(")) continue;
                 if (msg.GetType().GetField(info.Name).IsLiteral) continue;
                 if (info.GetValue(target) == null)
                 {
                     if (info.FieldType == typeof(string))
                         info.SetValue(target, "");
                     else if (info.FieldType.IsArray)
                         info.SetValue(target, Array.CreateInstance(info.FieldType.GetElementType(), 0));
                     else if (info.FieldType.FullName != null && !info.FieldType.FullName.Contains("Messages."))
                         info.SetValue(target, 0);
                     else
                         info.SetValue(target, Activator.CreateInstance(info.FieldType));
                 }
                 object field = info.GetValue(target);
                 //Randomize(info.FieldType, ref field, -1);
                 info.SetValue(target, field);
             }
         }
         else if (target is byte || T == typeof(byte))
         {
             target = (byte)r.Next(255);
         }
         else if (target is string || T == typeof(string))
         {
             //create a string of random length [1,100], composed of random chars
             int length = r.Next(100) + 1;
             byte[] buf = new byte[length];
             r.NextBytes(buf);  //fill the whole buffer with random bytes
             for (int i = 0; i < length; i++)
                 if (buf[i] == 0) //replace null chars with non-null random ones
                     buf[i] = (byte)(r.Next(254) + 1);
             buf[length - 1] = 0; //null terminate
             target = Encoding.ASCII.GetString(buf);
         }
         else if (target is bool || T == typeof(bool))
         {
             target = r.Next(2) == 1;
         }
         else if (target is int || T == typeof(int))
         {
             target = r.Next();
         }
         else if (target is uint || T == typeof(int))
         {
             target = (uint)r.Next();
         }
         else if (target is double || T == typeof(double))
         {
             target = r.NextDouble();
         }
         else if (target is TimeData || T == typeof(TimeData))
         {
             target = new TimeData((uint)r.Next(), (uint)r.Next());
         }
         else if (target is float || T == typeof(float))
         {
             target = (float)r.NextDouble();
         }
         else if (target is Int16 || T == typeof(Int16))
         {
             target = (Int16)r.Next(Int16.MaxValue + 1);
         }
         else if (target is UInt16 || T == typeof(UInt16))
         {
             target = (UInt16)r.Next(UInt16.MaxValue + 1);
         }
         else if (target is SByte || T == typeof(SByte))
         {
             target = (SByte)(r.Next(255) - 127);
         }
         else if (target is UInt64 || T == typeof(UInt64))
         {
             target = (UInt64)((uint)(r.Next() << 32)) | (uint)r.Next();
         }
         else if (target is Int64 || T == typeof(Int64))
         {
             target = (Int64)(r.Next() << 32) | r.Next();
         }
         else if (target is char || T == typeof(char))
         {
             target = (char)(byte)(r.Next(254) + 1);
         }
         else
         {
             throw new Exception("Unhandled randomization: " + T);
         }
     }
     else
     {
         int length = hardcodedarraylength != -1 ? hardcodedarraylength : r.Next(10);
         Type elem = T.GetElementType();
         Array field = Array.CreateInstance(elem, new int[] { length }, new int[] { 0 });
         for (int i = 0; i < length; i++)
         {
             object val = field.GetValue(i);
             RandomizeField(elem, ref val);
             field.SetValue(val, i);
         }
         target = field;
     }
 }