public void TestSwap()
        {
            using ( var target = new RpcOutputBuffer( ChunkBuffer.CreateDefault() ) )
            {
                using ( var stream = target.OpenWriteStream() )
                {
                    stream.Write( Enumerable.Range( 1, 10 ).Select( i => ( byte )i ).ToArray(), 0, 10 );
                }

                using ( var swapper = target.CreateSwapper() )
                {
                    CollectionAssert.AreEqual(
                        Enumerable.Range( 1, 10 ).Select( i => ( byte )i ).ToArray(),
                        swapper.ReadBytes()
                    );

                    swapper.WriteBytes( Enumerable.Range( 11, 30 ).Select( i => ( byte )i ) );
                }

                CollectionAssert.AreEqual(
                    Enumerable.Range( 11, 30 ).Select( i => ( byte )i ).ToArray(),
                    target.ReadBytes().ToArray()
                );
            }
        }
 private ResponseMessageSerializationContext( RpcOutputBuffer buffer, int messageId, object returnValue, RpcException exception, bool isVoid )
     : base(buffer)
 {
     this._messageId = messageId;
     this._returnValue = returnValue;
     this._isVoid = isVoid;
     this._exception = exception;
 }
		private static void TestSerializeCore( int id, object returnValue, bool isVoid, RpcException error )
		{
			if ( isVoid )
			{
				Assert.IsNull( returnValue, "Return value should not be specified in void." );
			}

			if ( error != null )
			{
				Assert.IsNull( returnValue, "Return value shoud not be specified in error." );
				Assert.IsFalse( isVoid, "isVoid should be false in error test." );
			}

			// TODO: Mock filters
			var objectTracingFilter = new SerializingResponseTracingFilterProvider();
			var binaryTracingFilter = new SerializedResponseTracingFilterProvider();
			var target =
				SerializerFactory.CreateResponseMessageSerializerWithTracer(
					objectTracingFilter,
					binaryTracingFilter,
					null,
					null
				);
			try
			{
				var buffer = new RpcOutputBuffer( ChunkBuffer.CreateDefault() );

				Assert.IsTrue( target.Serialize( id, returnValue, isVoid, error, buffer ).IsSuccess );
				byte[] serialized = buffer.ReadBytes().ToArray();
				var mpo =
					new MessagePackObject(
						new MessagePackObject[]
					{
						new MessagePackObject( ( int )MessageType.Response ),
						new MessagePackObject( ( uint )id ),
						error == null ? MessagePackObject.Nil : error.RpcError.Identifier,
						returnValue == null 
							? ( error == null ? MessagePackObject.Nil : error.GetExceptionMessage( false ) )
							: MessagePackObject.FromObject( returnValue )						
					}
					);
				var stream = new MemoryStream();
				Packer.Create( stream ).Pack( mpo );
				CollectionAssert.AreEqual(
					stream.ToArray(),
					serialized,
					"Expected:{0}{1}{0}Actual:{0}{2}",
					Environment.NewLine,
					mpo,
					new Unpacker( serialized ).UnpackObject()
				);
			}
			finally
			{
				Console.WriteLine( "OBJECT TRACE:{0}", objectTracingFilter.GetTrace() );
				Console.WriteLine( "BINARY TRACE:{0}", binaryTracingFilter.GetTrace() );
			}
		}
        /// <summary>
        ///		Initialize new instance for succeeded invocation of non-void method.
        /// </summary>
        /// <param name="buffer">Buffer to be written from serializer.</param>
        /// <param name="messageId">ID of this message.</param>
        /// <param name="exception">Exception thrown from the method.</param>
        /// <param name="isVoid">If invoked method is void then true.</param>
        internal ResponseMessageSerializationContext( RpcOutputBuffer buffer, int messageId, RpcException exception, bool isVoid )
            : this(buffer, messageId, null, exception, isVoid)
        {
            if ( exception == null )
            {
                throw new ArgumentNullException( "exception" );
            }

            Contract.EndContractBlock();
        }
        /// <summary>
        ///		Initialize new instance.
        /// </summary>
        /// <param name="buffer">
        ///		Buffer to store outbound data.
        /// </param>
        /// <exception cref="ArgumentNullException">
        ///		<paramref name="buffer"/> is null.
        /// </exception>
        protected MessageSerializationContext( RpcOutputBuffer buffer )
        {
            if ( buffer == null )
            {
                throw new ArgumentNullException( "buffer" );
            }

            Contract.EndContractBlock();

            this._buffer = buffer;
        }
        public static RpcOutputBuffer SerializeNotification( String method, params object[] arguments )
        {
            RpcOutputBuffer result = new RpcOutputBuffer( ChunkBuffer.CreateDefault() );
            var error =
                new RequestMessageSerializer(
                        Arrays<IFilterProvider<RequestMessageSerializationFilter>>.Empty,
                        Arrays<IFilterProvider<SerializedMessageFilter<MessageSerializationContext>>>.Empty,
                        Arrays<IFilterProvider<SerializedMessageFilter<MessageDeserializationContext>>>.Empty,
                        Arrays<IFilterProvider<RequestMessageDeserializationFilter>>.Empty,
                        null
                ).Serialize( null, method, arguments, result );
            if ( !error.IsSuccess )
            {
                throw error.ToException();
            }

            return result;
        }
        public void TestReadWrite()
        {
            using ( var target = new RpcOutputBuffer( ChunkBuffer.CreateDefault() ) )
            {
                using ( var stream = target.OpenWriteStream() )
                {
                    stream.Write( Enumerable.Range( 1, 10 ).Select( i => ( byte )i ).ToArray(), 0, 10 );
                    stream.Write( Enumerable.Range( 11, 10 ).Select( i => ( byte )i ).ToArray(), 0, 10 );
                }

                using ( var stream = target.OpenWriteStream() )
                {
                    stream.Write( Enumerable.Range( 21, 10 ).Select( i => ( byte )i ).ToArray(), 0, 10 );
                }

                using ( var stream = target.OpenWriteStream() ) { }

                using ( var stream = target.OpenWriteStream() )
                {
                    stream.Write( Enumerable.Range( 31, 10 ).Select( i => ( byte )i ).ToArray(), 0, 10 );
                }

                using ( var stream = target.OpenWriteStream() )
                {
                    stream.Write( new byte[ 0 ], 0, 0 );
                }

                using ( var stream = target.OpenWriteStream() )
                {
                    stream.Write( Enumerable.Range( 41, 10 ).Select( i => ( byte )i ).ToArray(), 0, 10 );
                }

                CollectionAssert.AreEqual(
                    Enumerable.Range( 1, 50 ).Select( i => ( byte )i ).ToArray(),
                    target.ReadBytes()
                );
            }
        }
        internal RequestMessageSerializationContext( RpcOutputBuffer buffer, int? messageId, string methodName, IList<object> arguments )
            : base(buffer)
        {
            if ( methodName == null )
            {
                throw new ArgumentNullException( "methodName" );
            }

            if ( String.IsNullOrWhiteSpace( methodName ) )
            {
                throw new ArgumentException( "'methodName' cannot be empty.", "methodName" );
            }

            if ( arguments == null )
            {
                throw new ArgumentNullException( "arguments" );
            }

            Contract.EndContractBlock();

            this._messageId = messageId;
            this._methodName = methodName;
            this._arguments = arguments;
        }
 /// <summary>
 ///		Initialize new instance for succeeded invocation of void method.
 /// </summary>
 /// <param name="buffer">Buffer to be written from serializer.</param>
 /// <param name="messageId">ID of this message.</param>
 internal ResponseMessageSerializationContext( RpcOutputBuffer buffer, int messageId )
     : this(buffer, messageId, null, null, true)
 {
 }
        public void TestSwap_WriteBytesNull()
        {
            using ( var target = new RpcOutputBuffer( ChunkBuffer.CreateDefault() ) )
            {
                using ( var stream = target.OpenWriteStream() )
                {
                    stream.Write( Enumerable.Range( 1, 10 ).Select( i => ( byte )i ).ToArray(), 0, 10 );
                }

                using ( var swapper = target.CreateSwapper() )
                {
                    swapper.WriteBytes( null );
                }
            }
        }
        public void TestSwap_WriteBytesEmpty()
        {
            using ( var target = new RpcOutputBuffer( ChunkBuffer.CreateDefault() ) )
            {
                using ( var stream = target.OpenWriteStream() )
                {
                    stream.Write( Enumerable.Range( 1, 10 ).Select( i => ( byte )i ).ToArray(), 0, 10 );
                }

                using ( var swapper = target.CreateSwapper() )
                {
                    swapper.WriteBytes( Enumerable.Empty<byte>() );
                }

                Assert.AreEqual( 0, target.ReadBytes().Count() );
            }
        }
 public void TestSerialize_Request()
 {
     // TODO: Mock filters
     var objectTracingFilter = new SerializingRequestTracingFilterProvider();
     var binaryTracingFilter = new SerializedRequestTracingFilterProvider();
     var target =
         SerializerFactory.CreateRequestMessageSerializerWithTracer(
             objectTracingFilter,
             binaryTracingFilter,
             null,
             null
         );
     try
     {
         var id = Environment.TickCount;
         var method = Guid.NewGuid().ToString();
         var args = new object[] { 1, "String", null, true };
         var buffer = new RpcOutputBuffer( ChunkBuffer.CreateDefault() );
         Assert.IsTrue( target.Serialize( id, method, args, buffer ).IsSuccess );
         byte[] serialized = buffer.ReadBytes().ToArray();
         var mpo =
             new MessagePackObject(
                 new MessagePackObject[]
                 {
                     new MessagePackObject( ( int )MessageType.Request ),
                     new MessagePackObject( ( uint )id ),
                     new MessagePackObject( method ),
                     new MessagePackObject[]
                     {
                         new MessagePackObject( 1 ),
                         new MessagePackObject( "String" ),
                         MessagePackObject.Nil,
                         new MessagePackObject( true )
                     }
                 }
             );
         var stream = new MemoryStream();
         Packer.Create( stream ).Pack( mpo );
         CollectionAssert.AreEqual( stream.ToArray(), serialized );
     }
     finally
     {
         Console.WriteLine( "OBJECT TRACE:{0}", objectTracingFilter.GetTrace() );
         Console.WriteLine( "BINARY TRACE:{0}", binaryTracingFilter.GetTrace() );
     }
 }
        /// <summary>
        ///		Serialize RPC call to specified buffer.
        /// </summary>
        /// <param name="messageId">ID of message. If message is notification message, specify null.</param>
        /// <param name="method">Method name to be called.</param>
        /// <param name="arguments">Arguments of method call.</param>
        /// <param name="buffer">Buffer to be set serialized stream.</param>
        /// <returns>Error message of serialization.</returns>
        /// <exception cref="ArgumentNullException">
        ///		<paramref name="method"/>, <paramref name="arguments"/>, or <paramref name="buffer"/> is null.
        /// </exception>
        /// <exception cref="ArgumentException">
        ///		<paramref name="method"/> is illegal.
        /// </exception>
        public RpcErrorMessage Serialize( int? messageId, string method, IList<object> arguments, RpcOutputBuffer buffer )
        {
            if ( method == null )
            {
                throw new ArgumentNullException( "method" );
            }

            // TODO: more strict validation.
            if ( String.IsNullOrWhiteSpace( method ) )
            {
                throw new ArgumentException( "'method' must not be empty nor blank.", "method" );
            }

            if ( arguments == null )
            {
                throw new ArgumentNullException( "arguments" );
            }

            if ( buffer == null )
            {
                throw new ArgumentNullException( "buffer" );
            }

            Contract.EndContractBlock();

            var context = new RequestMessageSerializationContext( buffer, messageId, method, arguments );

            foreach ( var preSerializationFilter in this._preSerializationFilters )
            {
                preSerializationFilter.GetFilter().Process( context );
                if ( !context.SerializationError.IsSuccess )
                {
                    return context.SerializationError;
                }
            }

            SerializeCore( buffer, messageId, context );
            if ( !context.SerializationError.IsSuccess )
            {
                return context.SerializationError;
            }

            foreach ( var postSerializationFilter in this._postSerializationFilters )
            {
                using ( var swapper = buffer.CreateSwapper() )
                {
                    swapper.WriteBytes( postSerializationFilter.GetFilter().Process( swapper.ReadBytes(), context ) );
                    if ( !context.SerializationError.IsSuccess )
                    {
                        return context.SerializationError;
                    }
                }
            }

            return RpcErrorMessage.Success;
        }
        private static void SerializeCore( RpcOutputBuffer buffer, int? messageId, RequestMessageSerializationContext context )
        {
            using ( var stream = buffer.OpenWriteStream() )
            using ( var packer = Packer.Create( stream ) )
            {
                packer.PackArrayHeader( messageId == null ? 3 : 4 );
                packer.Pack( ( int )( messageId == null ? MessageType.Notification : MessageType.Request ) );

                if ( messageId != null )
                {
                    packer.Pack( unchecked( ( uint )messageId.Value ) );
                }

                packer.PackString( context.MethodName );
                packer.PackItems( context.Arguments );
            }
        }
        /// <summary>
        ///		Serialize response message to specified buffer.
        /// </summary>
        /// <param name="messageId">ID of message.</param>
        /// <param name="returnValue">Return value of the method.</param>
        /// <param name="isVoid">If the method is void, then true.</param>
        /// <param name="exception">Exception thrown from the method.</param>
        /// <param name="buffer">Buffer to be stored serialized response stream.</param>
        /// <returns>Error information.</returns>
        public RpcErrorMessage Serialize( int messageId, object returnValue, bool isVoid, RpcException exception, RpcOutputBuffer buffer )
        {
            var context =
                exception != null
                ? new ResponseMessageSerializationContext( buffer, messageId, exception, isVoid )
                : ( isVoid ? new ResponseMessageSerializationContext( buffer, messageId ) : new ResponseMessageSerializationContext( buffer, messageId, returnValue ) );

            foreach ( var preSerializationFilter in this._preSerializationFilters )
            {
                preSerializationFilter.GetFilter().Process( context );
                if ( !context.SerializationError.IsSuccess )
                {
                    return context.SerializationError;
                }
            }

            SerializeCore( MessageType.Response, messageId, context );
            if ( !context.SerializationError.IsSuccess )
            {
                return context.SerializationError;
            }

            foreach ( var postSerializationFilter in this._postSerializationFilters )
            {
                using ( var swapper = buffer.CreateSwapper() )
                {
                    swapper.WriteBytes( postSerializationFilter.GetFilter().Process( swapper.ReadBytes(), context ) );
                    if ( !context.SerializationError.IsSuccess )
                    {
                        return context.SerializationError;
                    }
                }
            }

            return RpcErrorMessage.Success;
        }
 public RpcOutputBufferSwapper( RpcOutputBuffer enclosing )
 {
     Contract.Assert( enclosing != null );
     this._enclosing = enclosing;
 }
        public static RpcOutputBuffer SerializeResponse( int messageId, RpcException exception )
        {
            var result = new RpcOutputBuffer( ChunkBuffer.CreateDefault() );
            var error =
                new ResponseMessageSerializer(
                        Arrays<IFilterProvider<ResponseMessageSerializationFilter>>.Empty,
                        Arrays<IFilterProvider<SerializedMessageFilter<MessageSerializationContext>>>.Empty,
                        Arrays<IFilterProvider<SerializedMessageFilter<MessageDeserializationContext>>>.Empty,
                        Arrays<IFilterProvider<ResponseMessageDeserializationFilter>>.Empty,
                        null
                ).Serialize( messageId, null, false, exception, result );
            if ( !error.IsSuccess )
            {
                throw error.ToException();
            }

            return result;
        }
        protected override sealed void SendCore( RpcServerSession session, MessageType messageType, int messageId, object returnValue, bool isVoid, Exception exception )
        {
            RpcException rpcException = exception as RpcException;
            if ( rpcException == null && exception != null )
            {
                rpcException = new RpcException( RpcError.CallError, "Remote method throws exception.", exception.ToString() );
            }

            // FIXME: Buffer strategy
            RpcOutputBuffer buffer = new RpcOutputBuffer( ChunkBuffer.CreateDefault() );
            var error = this._responseSerializer.Serialize( messageId, returnValue, isVoid, rpcException, buffer );
            if ( !error.IsSuccess )
            {
                this._eventLoop.HandleError( new RpcTransportErrorEventArgs( RpcTransportOperation.Deserialize, messageId, error ) );
                return;
            }

            this._eventLoop.SendAsync( session.Context, buffer.ReadBytes() );
        }
 /// <summary>
 ///		Initialize new instance for succeeded invocation of non-void method.
 /// </summary>
 /// <param name="buffer">Buffer to be written from serializer.</param>
 /// <param name="messageId">ID of this message.</param>
 /// <param name="returnValue">Return value returned from the method.</param>
 internal ResponseMessageSerializationContext( RpcOutputBuffer buffer, int messageId, object returnValue )
     : this(buffer, messageId, returnValue, null, false)
 {
 }