Skip to content

Repository files navigation

ByteOps

License

Utility functions for reading and writing primitive values from byte collections with explicit byte order and word order control.

Features

  • Multiple byte sources: byte[], java.nio.ByteBuffer, and Netty ByteBuf
  • Four byte ordering variations: Big-endian, little-endian, and word-swapped variants
  • Unsigned type support: Optional modules for jOOU and Eclipse Milo unsigned types
  • Zero dependencies: Core module has no runtime dependencies (besides JSpecify annotations)
  • Java 11+: Compatible with Java 11 and later

Installation

Add the dependency to your pom.xml:

<dependency>
<groupId>com.digitalpetri.util</groupId>
<artifactId>byteops</artifactId>
<version>0.2.1</version>
</dependency>

Available Modules

ModuleArtifact IDDescription
Corebyteopsbyte[] and ByteBuffer support
Nettybyteops-nettyNetty ByteBuf support
Unsigned (jOOU)byteops-unsignedUByte, UShort, UInteger, ULong via jOOU
Unsigned (Milo)byteops-miloUnsigned types from Eclipse Milo

Quick Start

Reading Values

importcom.digitalpetri.util.byteops.ByteArrayByteOps;
importcom.digitalpetri.util.byteops.ByteOps;
// Get a ByteOps instance for your preferred byte orderingByteOps<byte[]> ops = ByteArrayByteOps.BIG_ENDIAN;
byte[] data = newbyte[] {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
shorts = ops.getShort(data, 0); // 0x0001inti = ops.getInt(data, 0); // 0x00010203longl = ops.getLong(data, 0); // 0x0001020304050607Lfloatf = ops.getFloat(data, 0); // Float.intBitsToFloat(0x00010203)doubled = ops.getDouble(data, 0); // Double.longBitsToDouble(0x0001020304050607L)

Writing Values

ByteOps<byte[]> ops = ByteArrayByteOps.LITTLE_ENDIAN;
byte[] buffer = newbyte[8];
ops.setInt(buffer, 0, 0x01020304);
ops.setInt(buffer, 4, 0x05060708);
// buffer: [0x04, 0x03, 0x02, 0x01, 0x08, 0x07, 0x06, 0x05]

Working with Arrays

ByteOps<byte[]> ops = ByteArrayByteOps.BIG_ENDIAN;
// Read an array of ints (2 ints = 8 bytes)byte[] data = newbyte[] {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
int[] ints = ops.getIntArray(data, 0, 2); // [0x00010203, 0x04050607]// Write an array of shortsbyte[] buffer = newbyte[4];
ops.setShortArray(buffer, 0, newshort[] {0x0102, 0x0304});
// buffer: [0x01, 0x02, 0x03, 0x04]

With ByteBuffer

importcom.digitalpetri.util.byteops.ByteBufferByteOps;
importjava.nio.ByteBuffer;
ByteOps<ByteBuffer> ops = ByteBufferByteOps.BIG_ENDIAN;
ByteBufferbuffer = ByteBuffer.allocate(8);
ops.setLong(buffer, 0, 0x0102030405060708L);
longvalue = ops.getLong(buffer, 0); // 0x0102030405060708L

With Netty ByteBuf

importcom.digitalpetri.util.byteops.netty.ByteBufByteOps;
importio.netty.buffer.ByteBuf;
importio.netty.buffer.Unpooled;
ByteOps<ByteBuf> ops = ByteBufByteOps.LITTLE_ENDIAN;
ByteBufbuf = Unpooled.buffer(8);
buf.writeZero(8); // ensure writable bytesops.setLong(buf, 0, 0x0102030405060708L);
longvalue = ops.getLong(buf, 0); // 0x0102030405060708L

Unsigned Types (jOOU)

importcom.digitalpetri.util.byteops.unsigned.UnsignedByteOps;
importorg.joou.UInteger;
ByteOps<byte[]> baseOps = ByteArrayByteOps.BIG_ENDIAN;
UnsignedByteOps<byte[]> ops = UnsignedByteOps.of(baseOps);
byte[] data = newbyte[] {(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF};
UIntegervalue = ops.getUInt(data, 0); // 4294967295 (not -1)

Byte Ordering

Four byte ordering variations are available for each implementation:

ConstantByte OrderWord Order
BIG_ENDIANBigHigh-Low
LITTLE_ENDIANLittleHigh-Low
BIG_ENDIAN_LOW_HIGHBigLow-High
LITTLE_ENDIAN_LOW_HIGHLittleLow-High

Visual Example

For a 32-bit integer 0x01020304:

BIG_ENDIAN: [0x01, 0x02, 0x03, 0x04] (bytes: 1,2,3,4)
LITTLE_ENDIAN: [0x04, 0x03, 0x02, 0x01] (bytes: 4,3,2,1)
BIG_ENDIAN_LOW_HIGH: [0x03, 0x04, 0x01, 0x02] (words swapped: 3,4,1,2)
LITTLE_ENDIAN_LOW_HIGH: [0x02, 0x01, 0x04, 0x03] (words swapped: 2,1,4,3)

API Overview

The ByteOps<T> interface provides:

Single Value Operations

MethodSizeDescription
getBoolean / setBoolean1 bytefalse = 0, true = non-zero
getByte / setByte1 byteSigned byte
getShort / setShort2 bytesSigned 16-bit integer
getInt / setInt4 bytesSigned 32-bit integer
getLong / setLong8 bytesSigned 64-bit integer
getFloat / setFloat4 bytesIEEE 754 single-precision
getDouble / setDouble8 bytesIEEE 754 double-precision

Array Operations

  • get*Array / set*Array - Primitive arrays (boolean[], byte[], short[], etc.)
  • getBoxed*Array / setBoxed*Array - Boxed arrays (Boolean[], Byte[], Short[], etc.)

Development

Requirements

  • JDK 17 is required to build (via Maven Toolchains)
  • Target: Java 11 bytecode

Maven Toolchains Setup

Create or edit ~/.m2/toolchains.xml:

<?xml version="1.0" encoding="UTF-8"?>
<toolchains>
<toolchain>
<type>jdk</type>
<provides>
<version>17</version>
</provides>
<configuration>
<jdkHome>/path/to/your/jdk-17</jdkHome>
</configuration>
</toolchain>
</toolchains>

Build Commands

mvn clean package # Build all modules
mvn test# Run tests
mvn spotless:apply # Format code (Google Java Format)
mvn spotless:check # Check code formatting

Project Structure

byteops/
├── byteops/ # Core module (byte[], ByteBuffer)
├── byteops-netty/ # Netty ByteBuf support
├── byteops-unsigned/ # jOOU unsigned types (UByte, UShort, UInteger, ULong)
└── byteops-milo/ # Eclipse Milo unsigned types

License

This project is licensed under the Eclipse Public License 2.0.

About

Utility functions for getting values from and setting values into collections of bytes, taking into account byte order and word order.

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Used by

Contributors

Languages