// Path: src/main/java/com/healthmarketscience/rmiio/PacketInputStream.java
// public abstract class PacketInputStream extends InputStream
// {
//   /** target size of packets returned from packet related methods */
//   public static final int DEFAULT_PACKET_SIZE = 1024;
// 
//   /** empty packet.  useful for returns from partial reads where no data is
//       currently available, but it's not EOF. */
//   protected static final byte[] EMPTY_PACKET = new byte[0];
// 
//   /** the packet size for buffers created in the overflow buffer list */
//   private final int _packetSize;
//   /** whether or not packet reading should accept partial packets by default.
//       allowing partial packet reads will generally cause more remote calls, but
//       should reduce latency per-object */
//   private final boolean _noDelay;
// 
//   public PacketInputStream() {
//     this(DEFAULT_PACKET_SIZE);
//   }
// 
//   public PacketInputStream(int packetSize) {
//     this(packetSize, false);
//   }
// 
//   public PacketInputStream(int packetSize, boolean noDelay) {
//     _packetSize = packetSize;
//     _noDelay = noDelay;
//   }
// 
//   public int getPacketSize() {
//     return _packetSize;
//   }
// 
//   public boolean getNoDelay() {
//     return _noDelay;
//   }
// 
//   /**
//    * Gets the next "packet" from the internal buffer and returns it (if any).
//    * By default, this method will block until a fully filled packet is created
//    * (equivalent to calling <code>readPacket(false)</code>).  If noDelay is
//    * enabled, this method will allow partial packet reads (equivalent to
//    * calling <code>readPacket(true)</code>).
//    *
//    * @return a fully filled array of byte's or <code>null</code> if the end of
//    *         stream has been reached
//    */
//   public byte[] readPacket()
//     throws IOException
//   {
//     return readPacket(_noDelay);
//   }
// 
//   /**
//    * Gets the next "packet" from the internal buffer and returns it (if any).
//    * This method may block until a full packet is read, depending on the value
//    * of readPartial.
//    *
//    * @param readPartial iff <code>false</code>, may block until a full packet
//    *                    is read (or EOF), otherwise will return as much data
//    *                    as is currently available (which may be 0).
//    * @return a fully filled array of byte's or <code>null</code> if the end of
//    *         stream has been reached.  if no data is available but EOF has not
//    *         been reached, the returned buffer will have length 0.
//    */
//   public abstract byte[] readPacket(boolean readPartial)
//     throws IOException;
// 
// 
//   /**
//    * Returns the number of full packets which can be read without blocking.
//    */
//   public abstract int packetsAvailable()
//     throws IOException;
// 
// 
//   /**
//    * Reads a packet of data from the given input stream.  The given packet is
//    * filled and returned if possible.  If not enough bytes are available, a
//    * new packet will be created and returned.  If the stream is empty, {@code
//    * null} will be returned.
//    *
//    * @param in the InputStream from which to read data
//    * @param packet the potential output packet (if enough data is available)
//    * @return a filled packet of data if any available, {@code null} if the
//    *         stream is empty
//    */
//   public static byte[] readPacket(InputStream in, byte[] packet)
//     throws IOException
//   {
//     int readLen = in.read(packet, 0, packet.length);
//     if(readLen > 0) {
// 
//       if(readLen < packet.length) {
//         // shrink buffer for output
//         byte[] tmpPacket = new byte[readLen];
//         System.arraycopy(packet, 0, tmpPacket, 0, readLen);
//         packet = tmpPacket;
//       }
//       return packet;
// 
//     } else if(readLen == 0) {
// 
//       return PacketInputStream.EMPTY_PACKET;
//     }
//     return null;
//   }
// 
// }
// 
// Path: src/main/java/com/healthmarketscience/rmiio/PacketOutputStream.java
// public abstract class PacketOutputStream extends OutputStream
// {
// 
//   public PacketOutputStream() {
//   }
// 
//   /**
//    * Puts the given "packet" into the output stream.  The packet should be
//    * filled with data.  The caller is giving control of the buffer to the
//    * PacketOutputStream, and therefore should not attempt to use the byte[]
//    * again.
//    *
//    * @param packet fully filled array of bytes to give to the OutputStream
//    */
//   public abstract void writePacket(byte[] packet)
//     throws IOException;
// 
// }


import java.io.IOException;
import java.nio.BufferUnderflowException;
import java.util.ArrayDeque;
import java.util.Deque;
import com.healthmarketscience.rmiio.PacketInputStream;
import com.healthmarketscience.rmiio.PacketOutputStream;
      return(_writePosition - _readPosition);
    }

    /** @return <code>true</code> if this buffer has as many bytes to read as
                its capacity, <code>false</code> otherwise */
    public boolean isFullToCapacity() {
      return(readRemaining() == _buf.length);
    }

    /** @return <code>true</code> if the buffer has no more space for writing
                or at least the given packetSize number of bytes,
                <code>false</code> otherwise */
    public boolean isFullPacket(int packetSize) {
      return(!hasWriteRemaining() || (readRemaining() >= packetSize));
    }

    public void clear() {
      _readPosition = _writePosition = 0;
    }

  }

  /**
   * PacketInputStream implementation which reads from a PipeBuffer.  One
   * hiccup here is that the single byte {@link #read()} method may fail if an
   * attempt is made to read a byte when none are in the PipeBuffer (as this
   * method is supposed to block in that case and this implementation has no
   * facility for blocking), so avoid that method call if at all
   * possible. Note, implementation is not synchronized.
   */
// Path: src/main/java/com/healthmarketscience/rmiio/PacketInputStream.java
// public abstract class PacketInputStream extends InputStream
// {
//   /** target size of packets returned from packet related methods */
//   public static final int DEFAULT_PACKET_SIZE = 1024;
// 
//   /** empty packet.  useful for returns from partial reads where no data is
//       currently available, but it's not EOF. */
//   protected static final byte[] EMPTY_PACKET = new byte[0];
// 
//   /** the packet size for buffers created in the overflow buffer list */
//   private final int _packetSize;
//   /** whether or not packet reading should accept partial packets by default.
//       allowing partial packet reads will generally cause more remote calls, but
//       should reduce latency per-object */
//   private final boolean _noDelay;
// 
//   public PacketInputStream() {
//     this(DEFAULT_PACKET_SIZE);
//   }
// 
//   public PacketInputStream(int packetSize) {
//     this(packetSize, false);
//   }
// 
//   public PacketInputStream(int packetSize, boolean noDelay) {
//     _packetSize = packetSize;
//     _noDelay = noDelay;
//   }
// 
//   public int getPacketSize() {
//     return _packetSize;
//   }
// 
//   public boolean getNoDelay() {
//     return _noDelay;
//   }
// 
//   /**
//    * Gets the next "packet" from the internal buffer and returns it (if any).
//    * By default, this method will block until a fully filled packet is created
//    * (equivalent to calling <code>readPacket(false)</code>).  If noDelay is
//    * enabled, this method will allow partial packet reads (equivalent to
//    * calling <code>readPacket(true)</code>).
//    *
//    * @return a fully filled array of byte's or <code>null</code> if the end of
//    *         stream has been reached
//    */
//   public byte[] readPacket()
//     throws IOException
//   {
//     return readPacket(_noDelay);
//   }
// 
//   /**
//    * Gets the next "packet" from the internal buffer and returns it (if any).
//    * This method may block until a full packet is read, depending on the value
//    * of readPartial.
//    *
//    * @param readPartial iff <code>false</code>, may block until a full packet
//    *                    is read (or EOF), otherwise will return as much data
//    *                    as is currently available (which may be 0).
//    * @return a fully filled array of byte's or <code>null</code> if the end of
//    *         stream has been reached.  if no data is available but EOF has not
//    *         been reached, the returned buffer will have length 0.
//    */
//   public abstract byte[] readPacket(boolean readPartial)
//     throws IOException;
// 
// 
//   /**
//    * Returns the number of full packets which can be read without blocking.
//    */
//   public abstract int packetsAvailable()
//     throws IOException;
// 
// 
//   /**
//    * Reads a packet of data from the given input stream.  The given packet is
//    * filled and returned if possible.  If not enough bytes are available, a
//    * new packet will be created and returned.  If the stream is empty, {@code
//    * null} will be returned.
//    *
//    * @param in the InputStream from which to read data
//    * @param packet the potential output packet (if enough data is available)
//    * @return a filled packet of data if any available, {@code null} if the
//    *         stream is empty
//    */
//   public static byte[] readPacket(InputStream in, byte[] packet)
//     throws IOException
//   {
//     int readLen = in.read(packet, 0, packet.length);
//     if(readLen > 0) {
// 
//       if(readLen < packet.length) {
//         // shrink buffer for output
//         byte[] tmpPacket = new byte[readLen];
//         System.arraycopy(packet, 0, tmpPacket, 0, readLen);
//         packet = tmpPacket;
//       }
//       return packet;
// 
//     } else if(readLen == 0) {
// 
//       return PacketInputStream.EMPTY_PACKET;
//     }
//     return null;
//   }
// 
// }
// 
// Path: src/main/java/com/healthmarketscience/rmiio/PacketOutputStream.java
// public abstract class PacketOutputStream extends OutputStream
// {
// 
//   public PacketOutputStream() {
//   }
// 
//   /**
//    * Puts the given "packet" into the output stream.  The packet should be
//    * filled with data.  The caller is giving control of the buffer to the
//    * PacketOutputStream, and therefore should not attempt to use the byte[]
//    * again.
//    *
//    * @param packet fully filled array of bytes to give to the OutputStream
//    */
//   public abstract void writePacket(byte[] packet)
//     throws IOException;
// 
// }


// Path: src/main/java/com/healthmarketscience/rmiio/util/PipeBuffer.java
import java.io.IOException;
import java.nio.BufferUnderflowException;
import java.util.ArrayDeque;
import java.util.Deque;
import com.healthmarketscience.rmiio.PacketInputStream;
import com.healthmarketscience.rmiio.PacketOutputStream;

      return(_writePosition - _readPosition);
    }

    /** @return <code>true</code> if this buffer has as many bytes to read as
                its capacity, <code>false</code> otherwise */
    public boolean isFullToCapacity() {
      return(readRemaining() == _buf.length);
    }

    /** @return <code>true</code> if the buffer has no more space for writing
                or at least the given packetSize number of bytes,
                <code>false</code> otherwise */
    public boolean isFullPacket(int packetSize) {
      return(!hasWriteRemaining() || (readRemaining() >= packetSize));
    }

    public void clear() {
      _readPosition = _writePosition = 0;
    }

  }

  /**
   * PacketInputStream implementation which reads from a PipeBuffer.  One
   * hiccup here is that the single byte {@link #read()} method may fail if an
   * attempt is made to read a byte when none are in the PipeBuffer (as this
   * method is supposed to block in that case and this implementation has no
   * facility for blocking), so avoid that method call if at all
   * possible. Note, implementation is not synchronized.
   */
  public static class InputStreamAdapter extends PacketInputStream