Interface DataBuf

All Superinterfaces:
AutoCloseable
All Known Subinterfaces:
DataBuf.Mutable

public interface DataBuf extends AutoCloseable
Represents an immutable buffer, which is essentially a wrapper around some kind of readable buffer. By default, CloudNet wraps netty buffer instances and delegates each method call to them.

However, a data buf does not allow (in comparison to other wrappers) the random access to bytes at specific positions. But it must be possible for a reader to store the current position of the buffer and return to it (for example, after reading). This is done by starting a transaction using startTransaction(), reading or writing to the buffer and restoring the previous position by using redoTransaction(). Note: This will not remove bytes written to the buffer, other writes will, however, start from the original index and override the written bytes.

Other operations should work as expected on a buffer, reading should always start from the head of the buffer, reflecting the operation over all other readers. If one reader reads a byte from the buffer, the next one will start at the second byte in the buffer, not the first one.

Buffers are not required to be thread safe, they should be treated specially in these cases. Concurrent read and/or write operations might therefore produce (by default) unspecified results when data buffers are accessed concurrently.

To prevent exceptions during reading, it's worth noting that using readableBytes() > 0 it is possible to verify that there are still bytes left in the buffer to read.

It is not recommended using any constructor to create an instance of a data buf - you should get a factory instance for them and create your instance using the given factory methods.

Since:
4.0
See Also:
  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Interface
    Description
    static interface 
    Represents a mutable version of a data buf.
  • Method Summary

    Modifier and Type
    Method
    Description
    boolean
    Get if the current buffer is still accessible or if it was released already.
    Acquires this buffer once.
    int
    Get the amount of times this buffer was acquired.
    Advances the current reader offset of this buffer by the given delta.
    Converts this immutable buffer to a mutable one.
    void
    Closes this buffer.
    Creates a new, empty data buffer using the default buffer factory (currently a netty buffer factory).
    void
    Forcibly closes the buffer, ignoring the current acquire count.
    int
    Get the remaining number of bytes that are filled with readable content.
    Get a new byte buffer instance that shares the memory region of this buffer.
    boolean
    Reads a boolean from this buffer at the current reader index.
    byte
    Reads a byte from this buffer at the current reader index.
    byte[]
    Reads the next array of bytes from the buffer.
    char
    Reads a 16-bit (UTF-16) char from this buffer at the current reader index.
    Reads the next data buf from the buffer.
    double
    Reads a 64-bit double from this buffer at the current reader index.
    int
    Get the current reader offset.
    readerOffset(int offset)
    Sets the current reader offset of this buffer.
    float
    Reads a 32-bit float from this buffer at the current reader index.
    int
    Reads a 32-bit integer from this buffer at the current reader index.
    long
    Reads a 64-bit long from this buffer at the current reader index.
    <T> T
    readNullable(@NonNull Function<DataBuf,T> readerWhenNonNull)
    Reads the next requested data from the buffer.
    <T> T
    readNullable(@NonNull Function<DataBuf,T> readerWhenNonNull, T valueWhenNull)
    Reads the next requested data from the buffer.
    <T> T
    Reads the next object from the buffer at the current reader index.
    <T> T
    Reads the next object from the buffer at the current reader index.
    short
    Reads a 16-bit short from this buffer at the current reader index.
    Reads the next UTF-8 encoded string from the buffer.
    Reads the next unique id from the buffer at the current reader index.
    Redoes the currently running transaction on the buffer.
    void
    Closes this buffer.
    Starts a transaction to the buffer.
    byte[]
    Converts the remaining bytes in this buffer into a byte array.
  • Method Details

    • empty

      @NonNull static DataBuf.Mutable empty()
      Creates a new, empty data buffer using the default buffer factory (currently a netty buffer factory).
      Returns:
      a new empty buffer which is mutable.
    • readBoolean

      boolean readBoolean()
      Reads a boolean from this buffer at the current reader index. Exactly one byte is read from the buffer.
      Returns:
      the boolean representation of the byte at the current position.
      Throws:
      IndexOutOfBoundsException - if there are no more bytes to read.
      IllegalStateException - if this buffer was released.
    • readByte

      byte readByte()
      Reads a byte from this buffer at the current reader index. Exactly one byte is read from the buffer.
      Returns:
      the byte at the current reader position.
      Throws:
      IndexOutOfBoundsException - if there are no more bytes to read.
      IllegalStateException - if this buffer was released.
    • readInt

      int readInt()
      Reads a 32-bit integer from this buffer at the current reader index. Exactly four bytes are read from the buffer.
      Returns:
      the next integer in the buffer at the current reader index.
      Throws:
      IndexOutOfBoundsException - if there are less than four bytes to read.
      IllegalStateException - if this buffer was released.
    • readShort

      short readShort()
      Reads a 16-bit short from this buffer at the current reader index. Exactly two bytes are read from the buffer.
      Returns:
      the next short in the buffer at the current reader index.
      Throws:
      IndexOutOfBoundsException - if there are less than two bytes to read.
      IllegalStateException - if this buffer was released.
    • readLong

      long readLong()
      Reads a 64-bit long from this buffer at the current reader index. Exactly eight bytes are read from the buffer.
      Returns:
      the next long in the buffer at the current reader index.
      Throws:
      IndexOutOfBoundsException - if there are less than eight bytes to read.
      IllegalStateException - if this buffer was released.
    • readFloat

      float readFloat()
      Reads a 32-bit float from this buffer at the current reader index. Exactly four bytes are read from the buffer.
      Returns:
      the next float in the buffer at the current reader index.
      Throws:
      IndexOutOfBoundsException - if there are less than four bytes to read.
      IllegalStateException - if this buffer was released.
    • readDouble

      double readDouble()
      Reads a 64-bit double from this buffer at the current reader index. Exactly eight bytes are read from the buffer.
      Returns:
      the next double in the buffer at the current reader index.
      Throws:
      IndexOutOfBoundsException - if there are less than eight bytes to read.
      IllegalStateException - if this buffer was released.
    • readChar

      char readChar()
      Reads a 16-bit (UTF-16) char from this buffer at the current reader index. Exactly two bytes are read from the buffer.
      Returns:
      the next UTF-16 char in the buffer at the current reader index.
      Throws:
      IndexOutOfBoundsException - if there are less than two bytes to read.
      IllegalStateException - if this buffer was released.
    • readByteArray

      byte[] readByteArray()
      Reads the next array of bytes from the buffer. A byte array is serialized in a special way. The bytes in the buffer are prefixed with the number of bytes in the array. Two steps are made to read an array from the buffer:
      1. The number of bytes in the following array are read from the buffer (by default a var int).
      2. The number of bytes the array is prefixed with are read from the buffer and put into a new array.

      As the operation is dynamic there is no way to pre-calculate the amount of bytes needed to read the next byte array.

      Returns:
      the next byte array in the buffer at the current reader index.
      Throws:
      IndexOutOfBoundsException - if there are fewer bytes than expected in the buffer.
      IllegalStateException - if this buffer was released.
    • readUniqueId

      @NonNull @NonNull UUID readUniqueId()
      Reads the next unique id from the buffer at the current reader index. The operation reads two longs from the buffer: the most significant bits of the unique id, and the least significant bits of the unique id. This totals to exactly sixteen bytes which are read from the buffer.
      Returns:
      the next unique id in the buffer at the current reader index.
      Throws:
      IndexOutOfBoundsException - if there are less than sixteen bytes to read.
      IllegalStateException - if this buffer was released.
    • readString

      @NonNull @NonNull String readString()
      Reads the next UTF-8 encoded string from the buffer. A string during write is converted to a byte array containing all bytes in UTF-8 form. Reading just reverses this operation. See readByteArray() for an explanation how the read operation works in detail (it's the same operation, the result is just wrapped using the string constructor).
      Returns:
      the next string in the buffer at the current reader index.
      Throws:
      IndexOutOfBoundsException - if there are fewer bytes than expected in the buffer.
      IllegalStateException - if this buffer was released.
    • readDataBuf

      @NonNull @NonNull DataBuf readDataBuf()
      Reads the next data buf from the buffer. A data buf write works like a byte array write operation because the buffer is essentially just wrapping a byte array. See readByteArray() about the expected format.

      Buffers are not expected to be cross-implementation-compatible. For instance, a netty buffer can only read and write netty buffers.

      Returns:
      the data buf in the buffer at the current reader index.
      Throws:
      IndexOutOfBoundsException - if there are fewer bytes than expected in the buffer.
      IllegalStateException - if this buffer was released.
    • toByteArray

      byte[] toByteArray()
      Converts the remaining bytes in this buffer into a byte array. This operation moves the reader index to the end of the buffer.
      Returns:
      the remaining bytes in this buffer converted to a byte array.
      Throws:
      IndexOutOfBoundsException - if there are no more bytes to read.
      IllegalStateException - if this buffer was released.
    • readObject

      <T> T readObject(@NonNull @NonNull Class<T> type)
      Reads the next object from the buffer at the current reader index. The object is read using the default object mapper of the system.
      Type Parameters:
      T - the generic type of the object to read.
      Parameters:
      type - the type of the object to read.
      Returns:
      the next object in the buffer at the current reader index.
      Throws:
      IndexOutOfBoundsException - if there are no more bytes to read.
      IllegalStateException - if this buffer was released.
      See Also:
    • readObject

      <T> T readObject(@NonNull @NonNull Type type)
      Reads the next object from the buffer at the current reader index. The object is read using the default object mapper of the system.
      Type Parameters:
      T - the generic type of the object to read.
      Parameters:
      type - the type of the object to read.
      Returns:
      the next object in the buffer at the current reader index.
      Throws:
      IndexOutOfBoundsException - if there are no more bytes to read.
      IllegalStateException - if this buffer was released.
      See Also:
    • readNullable

      @Nullable <T> T readNullable(@NonNull @NonNull Function<DataBuf,T> readerWhenNonNull)
      Reads the next requested data from the buffer. This method call is equivalent to readNullable(readerWhenNonNull, null).
      Type Parameters:
      T - the generic type of the data to read.
      Parameters:
      readerWhenNonNull - the reader to read the data from the buffer when the next value is non-null.
      Returns:
      the value read from the buffer or the fallback value when the buffered contained null at the position.
      Throws:
      IndexOutOfBoundsException - if there are no more bytes to read.
      IllegalStateException - if this buffer was released.
    • readNullable

      <T> T readNullable(@NonNull @NonNull Function<DataBuf,T> readerWhenNonNull, @Nullable T valueWhenNull)
      Reads the next requested data from the buffer. To determine whether the given reader for further reading should be called, the boolean before the actual data is read. If the boolean is true, the following data is present (non-null), otherwise the given value to return when null is returned.
      Type Parameters:
      T - the generic type of the data to read.
      Parameters:
      readerWhenNonNull - the reader to read the data from the buffer when the next value is non-null.
      valueWhenNull - the value to return when the buffer contains a null value at the current reader index.
      Returns:
      the value read from the buffer or the fallback value when the buffered contained null at the position.
      Throws:
      IndexOutOfBoundsException - if there are no more bytes to read.
      IllegalStateException - if this buffer was released.
    • readableBytes

      int readableBytes()
      Get the remaining number of bytes that are filled with readable content.
      Returns:
      the remaining number of bytes that are filled with readable content.
    • readerOffset

      int readerOffset()
      Get the current reader offset. The next read to this buffer will happen at the returned offset.
      Returns:
      the current reader offset.
    • readerOffset

      @NonNull @Contract("_ -> this") @NonNull DataBuf readerOffset(int offset)
      Sets the current reader offset of this buffer. The next read will happen from the given offset.
      Parameters:
      offset - the new reader offset to use.
      Returns:
      this buffer, for chaining.
      Throws:
      IllegalStateException - if this buffer was released.
      IndexOutOfBoundsException - if the given offset is beyond the end of this buffer.
    • advanceReaderOffset

      @NonNull @Contract("_ -> this") @NonNull DataBuf advanceReaderOffset(int delta)
      Advances the current reader offset of this buffer by the given delta. The next read to this buffer happens at the current reader index plus the given delta. Note: the given delta cannot be negative.
      Parameters:
      delta - the number of bytes to move the reader index by.
      Returns:
      this buffer, for chaining.
      Throws:
      IllegalArgumentException - if the given delta is negative.
      IllegalStateException - if this buffer was released.
      IndexOutOfBoundsException - if advancing by the given delta would move beyond the end of this buffer.
    • readableNioBuffer

      Get a new byte buffer instance that shares the memory region of this buffer. The returned buffer is marked as read-only which prevents write operations to it. The initial byte buffer offset is the current reader offset, and it's limited to the number of readable bytes beyond the current reader offset.

      Note: this api is marked as experimental as the lifecycle of the returned buffer cannot be controlled. This means that a returned byte buffer instance can still refer to memory already released by this buffer.

      Returns:
      a read-only byte buffer sharing the memory region of this buffer, but with a separate position.
      Throws:
      IllegalStateException - if this buffer was released.
    • startTransaction

      @NonNull @NonNull DataBuf startTransaction()
      Starts a transaction to the buffer. Starting a transaction while another transaction is active will override the current transaction marker. A transaction can be redone by using redoTransaction().
      Returns:
      the same instance as used to call the method, for chaining.
    • redoTransaction

      @NonNull @NonNull DataBuf redoTransaction()
      Redoes the currently running transaction on the buffer. If no transaction was started before, the reader and writer index will go back to 0.
      Returns:
      the same instance as used to call the method, for chaining.
      Throws:
      IllegalStateException - if this buffer was released.
      IndexOutOfBoundsException - if an illegal action was made to buffer moving the reader or writer index.
    • asMutable

      Converts this immutable buffer to a mutable one. The underlying memory is not shared between this buffer and the newly constructed mutable one. The returned buffer range starts at the current reader position of this buffer.
      Returns:
      a mutable variant of this buffer.
      Throws:
      IllegalStateException - if this buffer was released.
    • accessible

      boolean accessible()
      Get if the current buffer is still accessible or if it was released already.
      Returns:
      if the current buffer is still accessible.
    • acquires

      int acquires()
      Get the amount of times this buffer was acquired. A number greater than zero indicates that this buffer is accessible and not released, a number equal or less than zero indicates that this buffer was released and is inaccessible.
      Returns:
      the amount of times this buffer was acquired.
    • acquire

      Acquires this buffer once. If a buffer gets acquired, further calls to release() will decrease the count, but only release the buffer if there were more release than acquire calls.
      Returns:
      the same instance as used to call the method, for chaining.
      Throws:
      IllegalStateException - if this buffer was released or was acquired too many times.
    • release

      void release()
      Closes this buffer. In case the acquire count is exactly 1, the buffer content will be released and this buffer becomes inaccessible. If the acquire count is greater than 1, the acquire count is decreased by one and the buffer stays accessible. If the buffer was already released, this method does nothing.
    • forceRelease

      void forceRelease()
      Forcibly closes the buffer, ignoring the current acquire count. The buffer will always be inaccessible after this method was invoked.
    • close

      void close()
      Closes this buffer. In case the acquire count is exactly 1, the buffer content will be released and this buffer becomes inaccessible. If the acquire count is greater than 1, the acquire count is decreased by one and the buffer stays accessible. If the buffer was already released, this method does nothing.
      Specified by:
      close in interface AutoCloseable