private void WriteValue(ref MessagePackWriter writer, BufferPoolBufferWriter bufferWriter, object item)
 {
     if (item == null)
     {
         writer.WriteNil();
     }
     else
     {
         //MessagePackSerializer.Serialize(item.GetType(), ref writer, item);
         writer.Flush();
         MessagePackSerializer.Serialize(item.GetType(), bufferWriter, item);
     }
 }
        public BufferSegment EncodeMessage(Message message)
        {
            var memBuffer = BufferPool.Get(256, true);
            var stream    = new BufferPoolMemoryStream(memBuffer, 0, memBuffer.Length, true, true, false, true);

            // Write 5 bytes for placeholder for length prefix
            stream.WriteByte(0);
            stream.WriteByte(0);
            stream.WriteByte(0);
            stream.WriteByte(0);
            stream.WriteByte(0);

            var bufferWriter = new BufferPoolBufferWriter(stream);
            var writer       = new MessagePackWriter(bufferWriter);

            switch (message.type)
            {
            case MessageTypes.StreamItem:
                // https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#streamitem-message-encoding-1
                // [2, Headers, InvocationId, Item]

                writer.WriteArrayHeader(4);

                writer.Write(2);
                WriteHeaders(ref writer);
                WriteString(ref writer, message.invocationId);
                WriteValue(ref writer, bufferWriter, message.item);

                break;

            case MessageTypes.Completion:
                // https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#completion-message-encoding-1
                // [3, Headers, InvocationId, ResultKind, Result?]

                byte resultKind = (byte)(!string.IsNullOrEmpty(message.error) ? /*error*/ 1 : message.result != null ? /*non-void*/ 3 : /*void*/ 2);

                writer.WriteArrayHeader(resultKind == 2 ? 4 : 5);

                writer.Write(3);
                WriteHeaders(ref writer);
                WriteString(ref writer, message.invocationId);
                writer.Write(resultKind);

                if (resultKind == 1)     // error
                {
                    WriteString(ref writer, message.error);
                }
                else if (resultKind == 3)     // non-void
                {
                    WriteValue(ref writer, bufferWriter, message.result);
                }

                break;

            case MessageTypes.Invocation:
            // https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#invocation-message-encoding-1
            // [1, Headers, InvocationId, NonBlocking, Target, [Arguments], [StreamIds]]

            case MessageTypes.StreamInvocation:
                // https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#streaminvocation-message-encoding-1
                // [4, Headers, InvocationId, Target, [Arguments], [StreamIds]]

                writer.WriteArrayHeader(message.streamIds != null ? 6 : 5);

                writer.Write((int)message.type);
                WriteHeaders(ref writer);
                WriteString(ref writer, message.invocationId);
                WriteString(ref writer, message.target);
                writer.WriteArrayHeader(message.arguments != null ? message.arguments.Length : 0);
                if (message.arguments != null)
                {
                    for (int i = 0; i < message.arguments.Length; ++i)
                    {
                        WriteValue(ref writer, bufferWriter, message.arguments[i]);
                    }
                }

                if (message.streamIds != null)
                {
                    writer.WriteArrayHeader(message.streamIds.Length);

                    for (int i = 0; i < message.streamIds.Length; ++i)
                    {
                        WriteValue(ref writer, bufferWriter, message.streamIds[i]);
                    }
                }

                break;

            case MessageTypes.CancelInvocation:
                // https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#cancelinvocation-message-encoding-1
                // [5, Headers, InvocationId]

                writer.WriteArrayHeader(3);

                writer.Write(5);
                WriteHeaders(ref writer);
                WriteString(ref writer, message.invocationId);

                break;

            case MessageTypes.Ping:
                // https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#ping-message-encoding-1
                // [6]

                writer.WriteArrayHeader(1);
                writer.Write(6);

                break;

            case MessageTypes.Close:
                // https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#close-message-encoding-1
                // [7, Error, AllowReconnect?]

                writer.WriteArrayHeader(string.IsNullOrEmpty(message.error) ? 1 : 2);

                writer.Write(7);
                if (!string.IsNullOrEmpty(message.error))
                {
                    WriteString(ref writer, message.error);
                }

                break;
            }

            writer.Flush();

            // get how much bytes got written to the buffer. This includes the 5 placeholder bytes too.
            int length = (int)stream.Position;

            // this is the length without the 5 placeholder bytes
            int contentLength = length - 5;

            // get the stream's internal buffer. We set the releaseBuffer flag to false, so we can use it safely.
            var buffer = stream.GetBuffer();

            // add varint length prefix
            byte prefixBytes = GetRequiredBytesForLengthPrefix(contentLength);

            WriteLengthAsVarInt(buffer, 5 - prefixBytes, contentLength);

            // return with the final segment
            return(new BufferSegment(buffer, 5 - prefixBytes, contentLength + prefixBytes));
        }