/// <summary>
 ///		Process response message after deserialization.
 /// </summary>
 /// <param name="context">Context information of deserializing message.</param>
 protected abstract void ProcessCore( ResponseMessageDeserializationContext context );
        private static void DeserializeCore( IEnumerable<byte> sequence, ResponseMessageDeserializationContext context )
        {
            using ( var unpacker = new Unpacker( sequence ) )
            {
                MessagePackObject? response = unpacker.UnpackObject();
                if ( response == null )
                {
                    if ( context.SerializationError.IsSuccess )
                    {
                        // Since entire stream was readed and its length was in quota, the stream may be coruppted.
                        context.SetSerializationError( new RpcErrorMessage( RpcError.MessageRefusedError, "Invalid message.", "Cannot deserialize message stream." ) );
                    }

                    return;
                }

                if ( !response.Value.IsTypeOf<IList<MessagePackObject>>().GetValueOrDefault() )
                {
                    context.SetSerializationError( new RpcErrorMessage( RpcError.MessageRefusedError, "Invalid message.", "Response message is not array." ) );
                    return;
                }

                var requestFields = response.Value.AsList();
                if ( requestFields.Count != 4 )
                {
                    context.SetSerializationError( new RpcErrorMessage( RpcError.MessageRefusedError, "Invalid message.", "Response message is not 4 element array." ) );
                    return;
                }

                if ( !requestFields[ 0 ].IsTypeOf<int>().GetValueOrDefault() )
                {
                    context.SetSerializationError( new RpcErrorMessage( RpcError.MessageRefusedError, "Invalid message.", "Message type of response message is not int 32." ) );
                    return;
                }

                if ( requestFields[ 0 ].AsInt32() != ( int )MessageType.Response )
                {
                    context.SetSerializationError( new RpcErrorMessage( RpcError.MessageRefusedError, "Invalid message.", "Message type of response message is not Response(2)." ) );
                    return;
                }

                if ( !requestFields[ 1 ].IsTypeOf<uint>().GetValueOrDefault() )
                {
                    context.SetSerializationError( new RpcErrorMessage( RpcError.MessageRefusedError, "Invalid message.", "Message ID of response message is not int32." ) );
                    return;
                }

                // For CLS compliance store uint32 value as int32.
                unchecked
                {
                    context.MessageId = ( int )requestFields[ 1 ].AsUInt32();
                }

                // Error is should be string identifier of error, but arbitary objects are supported.
                context.Error = requestFields[ 2 ];

                // If error is specified, this value should be nil by original spec, but currently should specify error information.
                context.DeserializedResult = requestFields[ 3 ];
            }
        }
        /// <summary>
        ///		Process response message after deserialization.
        /// </summary>
        /// <param name="context">Context information of deserializing message.</param>
        internal void Process( ResponseMessageDeserializationContext context )
        {
            Contract.Assert( context != null );

            this.ProcessCore( context );
        }
        /// <summary>
        ///		Deserialize response message from specified buffer.
        /// </summary>
        /// <param name="input">Buffer which stores serialized request/notification stream.</param>
        /// <param name="result">Deserialied packed message will be stored.</param>
        /// <returns>Error information.</returns>
        /// <exception cref="ArgumentNullException">
        ///		<paramref name="input"/> is null.
        /// </exception>
        /// <exception cref="InvalidOperationException">
        ///		Some filters violate contract.
        /// </exception>
        public RpcErrorMessage Deserialize( IEnumerable<byte> input, out ResponseMessage result )
        {
            if ( input == null )
            {
                throw new ArgumentNullException( "input" );
            }

            Contract.EndContractBlock();

            var context = new ResponseMessageDeserializationContext( input, this._maxRequestLength );
            var sequence = context.ReadBytes();

            foreach ( var preDeserializationFilter in this._preDeserializationFilters )
            {
                var processed = preDeserializationFilter.GetFilter().Process( sequence, context );
                if ( !context.SerializationError.IsSuccess )
                {
                    result = default( ResponseMessage );
                    return context.SerializationError;
                }

                if ( processed == null )
                {
                    throw new InvalidOperationException( "Deserialization filter did not return sequence." );
                }

                sequence = processed;
            }

            DeserializeCore( sequence, context );

            if ( !context.SerializationError.IsSuccess )
            {
                result = default( ResponseMessage );
                return context.SerializationError;
            }

            foreach ( var postDeserializationFilter in this._postDeserializationFilters )
            {
                postDeserializationFilter.GetFilter().Process( context );
                if ( !context.SerializationError.IsSuccess )
                {
                    result = default( ResponseMessage );
                    return context.SerializationError;
                }
            }

            if ( !context.Error.IsNil )
            {
                result = new ResponseMessage( context.MessageId, RpcException.FromMessage( context.Error, context.DeserializedResult ) );
            }
            else
            {
                result = new ResponseMessage( context.MessageId, context.DeserializedResult );
            }

            return RpcErrorMessage.Success;
        }