src/_boneyard/org/michailov/async/io/AsyncByteStreamReader.java
public CompletableFuture<Integer> readAsync(byte[] buff, int offset, int length, CompleteWhen completeWhen, long timeout, TimeUnit unit) {
        // There should be no outstanding operation on this reader.
        if (_asyncState != null) {
            throw new IllegalStateException("There is already a readAsync operation in progress. Await for the returned task to complete, and retry.");
        }
        
        // The buffer should be existent.
        if (buff == null) {
            throw new IllegalArgumentException("Argument buff may not be null.");
        }
        
        // The offset should be within the buffer's boundaries.
        if (offset < 0 || buff.length <= offset) {
            String message = String.format("Argument offset (%1$d) must be between 0 and %2$d, or the length of buff must be increased.", offset, buff.length - 1);
            throw new IllegalArgumentException(message);
        }
        
        // The combination of offset and length should be within the buffer's boundaries. 
        if (length < 0 || buff.length < offset + length) {
            String message = String.format("Argument length (%1$d) must be between 0 and %2$d, or the length of buff must be increased.", length, buff.length - 1 - offset);
            throw new IllegalArgumentException(message);
        }
        
        // If EOF has already been reported, the caller shouldn't have continued.
        if (_eofState == EOFState.REPORTED) {
            throw new IllegalStateException("Attempting to read past the end of stream.");
        }
        
        // If EOF was received from the stream, but hasn't been yet reported to the caller,
        // return a completed future with a result of EOF, and record that EOF has been reported to the caller.
        if (_eofState == EOFState.RECEIVED) {
            _eofState = EOFState.REPORTED;
            return CompletableFuture.completedFuture(Integer.valueOf(EOF));
        }
        
        // If the caller is requesting 0 bytes, return a completed future immediately. 
        if (length == 0) {
            return CompletableFuture.completedFuture(Integer.valueOf(0));
        }

        // Create a new operation state.
        // Cache everything that may be need through the end of this method because the state may get deleted before the return statement is reached. 
        _asyncState = new AsyncState(buff, offset, length, completeWhen, unit.toMillis(timeout));
        CompletableFuture<Integer> future = _asyncState.future;

        // Submit a new operation or complete synchronously.
        submitRead2();
        
        // Return the cached future reference which may or may not be completed by now. 
        return future;
    }
/**
     * Starts an asynchronous read operation.
     * <p>
     * This is a low-level API. You may find the corresponding overload that takes a ByteRingBuffer
     * more convenient. 
     * 
     * @param   buff            Buffer to read into.
     * @param   offset          Offset in the buffer to start placing bytes.
     * @param   length          Maximum number of bytes to be read. A smaller number may actually be read.
     * @param   completeWhen    When AVAILABLE, the returned future completes as soon as the first batch of
     *                          available bytes is read. 
     *                          When FULL, the returned future completes when either the buffer is full or
     *                          when there are no more bytes to read.
     * @param   timeout         The number of timeout units before the operation expires, or -1 for infinity.
     * @param   unit            The type of time units.
     * @return                  A CompletableFuture<Integer>. The result value is the number of bytes actually 
     *                          read, or -1 if an attempt to read from the end of stream was made. 
     */
Starts an asynchronous read operation.

This is a low-level API. You may find the corresponding overload that takes a ByteRingBuffer
more convenient.

@param   buff            Buffer to read into.
@param   offset          Offset in the buffer to start placing bytes.
@param   length          Maximum number of bytes to be read. A smaller number may actually be read.
@param   completeWhen    When AVAILABLE, the returned future completes as soon as the first batch of
available bytes is read.
When FULL, the returned future completes when either the buffer is full or
when there are no more bytes to read.
@param   timeout         The number of timeout units before the operation expires, or -1 for infinity.
@param   unit            The type of time units.
Starts an asynchronous read operation . This is a low - level API . You may find the corresponding overload that takes a ByteRingBuffer more convenient . @param buff Buffer to read into . @param offset Offset in the buffer to start placing bytes . @param length Maximum number of bytes to be read . A smaller number may actually be read . @param completeWhen When AVAILABLE the returned future completes as soon as the first batch of available bytes is read . When FULL the returned future completes when either the buffer is full or when there are no more bytes to read . @param timeout The number of timeout units before the operation expires or - 1 for infinity . @param unit The type of time units .
public CompletableFuture<Integer> readAsync(byte[] buff, int offset, int length, CompleteWhen completeWhen, long timeout, TimeUnit unit) {
        if (_asyncState != null) {
            throw new IllegalStateException("There is already a readAsync operation in progress. Await for the returned task to complete, and retry.");
        }
        if (buff == null) {
            throw new IllegalArgumentException("Argument buff may not be null.");
        }
        if (offset < 0 || buff.length <= offset) {
            String message = String.format("Argument offset (%1$d) must be between 0 and %2$d, or the length of buff must be increased.", offset, buff.length - 1);
            throw new IllegalArgumentException(message);
        }
        if (length < 0 || buff.length < offset + length) {
            String message = String.format("Argument length (%1$d) must be between 0 and %2$d, or the length of buff must be increased.", length, buff.length - 1 - offset);
            throw new IllegalArgumentException(message);
        }
        if (_eofState == EOFState.REPORTED) {
            throw new IllegalStateException("Attempting to read past the end of stream.");
        }
        if (_eofState == EOFState.RECEIVED) {
            _eofState = EOFState.REPORTED;
            return CompletableFuture.completedFuture(Integer.valueOf(EOF));
        }
        if (length == 0) {
            return CompletableFuture.completedFuture(Integer.valueOf(0));
        }
        _asyncState = new AsyncState(buff, offset, length, completeWhen, unit.toMillis(timeout));
        CompletableFuture<Integer> future = _asyncState.future;
        submitRead2();
        return future;
    }
public CompletableFuture < Integer > readAsync ( byte [ ] buff , int offset , int length , CompleteWhen completeWhen , long timeout , TimeUnit unit ) { if ( _asyncState != null ) { throw new IllegalStateException ( "There is already a readAsync operation in progress. Await for the returned task to complete, and retry." ) ; } if ( buff == null ) { throw new IllegalArgumentException ( "Argument buff may not be null." ) ; } if ( offset < 0 || buff . length <= offset ) { String message = String . format ( "Argument offset (%1$d) must be between 0 and %2$d, or the length of buff must be increased." , offset , buff . length - 1 ) ; throw new IllegalArgumentException ( message ) ; } if ( length < 0 || buff . length < offset + length ) { String message = String . format ( "Argument length (%1$d) must be between 0 and %2$d, or the length of buff must be increased." , length , buff . length - 1 - offset ) ; throw new IllegalArgumentException ( message ) ; } if ( _eofState == EOFState . REPORTED ) { throw new IllegalStateException ( "Attempting to read past the end of stream." ) ; } if ( _eofState == EOFState . RECEIVED ) { _eofState = EOFState . REPORTED ; return CompletableFuture . completedFuture ( Integer . valueOf ( EOF ) ) ; } if ( length == 0 ) { return CompletableFuture . completedFuture ( Integer . valueOf ( 0 ) ) ; } _asyncState = new AsyncState ( buff , offset , length , completeWhen , unit . toMillis ( timeout ) ) ; CompletableFuture < Integer > future = _asyncState . future ; submitRead2 ( ) ; return future ; }
Starts an asynchronous read operation.
Starts an asynchronous read operation .
// There should be no outstanding operation on this reader.
 // The buffer should be existent.
 // The offset should be within the buffer's boundaries.
 // The combination of offset and length should be within the buffer's boundaries. 
 // If EOF has already been reported, the caller shouldn't have continued.
 // If EOF was received from the stream, but hasn't been yet reported to the caller,
 // return a completed future with a result of EOF, and record that EOF has been reported to the caller.
 // If the caller is requesting 0 bytes, return a completed future immediately. 
 // Create a new operation state.
 // Cache everything that may be need through the end of this method because the state may get deleted before the return statement is reached. 
 // Submit a new operation or complete synchronously.
 // Return the cached future reference which may or may not be completed by now. 
