private void WritePrimitive(BinaryWriter bw, object o, ETypeTag tag)
 {
     switch (tag)
     {
         case ETypeTag.Boolean:
             bw.Write((bool)o);
             break;
         case ETypeTag.Byte:
             bw.Write((byte)o);
             break;
         case ETypeTag.ByteArray:
             var b = (byte[])o;
             bw.Write(b.Length);
             bw.Write(b);
             break;
         case ETypeTag.Char:
             bw.Write((char)o);
             break;
         case ETypeTag.CharArray:
             var c = (char[])o;
             bw.Write(c.Length);
             bw.Write(c);
             break;
         case ETypeTag.Decimal:
             bw.Write((decimal)o);
             break;
         case ETypeTag.Double:
             bw.Write((double)o);
             break;
         case ETypeTag.Float:
             bw.Write((float)o);
             break;
         case ETypeTag.Int:
             bw.Write((int)o);
             break;
         case ETypeTag.Long:
             bw.Write((long)o);
             break;
         case ETypeTag.SByte:
             bw.Write((sbyte)o);
             break;
         case ETypeTag.Short:
             bw.Write((short)o);
             break;
         case ETypeTag.String:
             bw.Write((string)o);
             break;
         case ETypeTag.Uint:
             bw.Write((uint)o);
             break;
         case ETypeTag.Ulong:
             bw.Write((ulong)o);
             break;
         case ETypeTag.Ushort:
             bw.Write((ushort)o);
             break;
     }
 }
 private object ReadPrimitive(BinaryReader br, ETypeTag tag)
 {
     switch (tag)
     {
         case ETypeTag.Boolean:
             return br.ReadBoolean();
         case ETypeTag.Byte:
             return br.ReadByte();
         case ETypeTag.ByteArray:
             return br.ReadBytes(br.ReadInt32());
         case ETypeTag.Char:
             return br.ReadChar();
         case ETypeTag.CharArray:
             return br.ReadChars(br.ReadInt32());
         case ETypeTag.Decimal:
             return br.ReadDecimal();
         case ETypeTag.Double:
             return br.ReadDouble();
         case ETypeTag.Float:
             return br.ReadSingle();
         case ETypeTag.Int:
             return br.ReadInt32();
         case ETypeTag.Long:
             return br.ReadInt64();
         case ETypeTag.SByte:
             return br.ReadSByte();
         case ETypeTag.Short:
             return br.ReadInt16();
         case ETypeTag.String:
             return br.ReadString();
         case ETypeTag.Uint:
             return br.ReadUInt32();
         case ETypeTag.Ulong:
             return br.ReadUInt64();
         case ETypeTag.Ushort:
             return br.ReadUInt16();
         default:
             return null;
     }
 }