jam.types.base.sequences

Sequence type implementations for the JAM protocol.

Type Definitions

Array Types

  • Array[T, N]: Fixed-length array of any custom type T with size N

  • BitArray[N]: Fixed-length array of bits

  • ByteArray[N]: Fixed-length array of bytes

Vector Types

  • Vector[T]: Dynamic-length array of any custom type T

  • Bytes: Dynamic-length byte array

Encoding Format

Fixed-length Arrays

No length prefix, just elements:

Array[u8, 3]([1,2,3]) -> [01 02 03]
BitArray[8]([1,0,1,0,1,0,1,0]) -> [AA]  # 10101010
ByteArray[2]([1,2]) -> [01 02]

Dynamic Vectors

Length prefix followed by elements:

Vector[u8]([1,2]) -> [02 01 02]  # len=2, elements=[1,2]
Bytes([1,2,3]) -> [03 01 02 03]  # len=3, bytes=[1,2,3]

Implementation Details

Memory Layout

  • Arrays: Contiguous memory, no gaps

  • Vectors: Length prefix + contiguous elements

  • Bit arrays: Packed bits, no padding

  • Byte arrays: Raw bytes, no encoding

Size Validation

  • Fixed arrays: Exact size required

  • Bit arrays: Bit count must match

  • Vectors: Dynamic size with max limit

  • Byte arrays: Size validation on fixed variants

Error Handling

Common error cases:

  1. Size mismatch:

    if len(value) != self.size:
        raise ValueError(f"Expected {self.size} elements, got {len(value)}")
    
  2. Invalid element type:

    if not isinstance(element, element_type):
        raise TypeError(f"Invalid element type: {type(element)}")
    
  3. Buffer overflow:

    if len(buffer) - offset < needed_size:
        raise BufferError(f"Buffer too small: need {needed_size} bytes")
    

Examples

Fixed Arrays

from jam.types.base.sequences import Array
from jam.types.base.integers import U8

# Create fixed array of 3 U8 values
@decodable_array(U8, 3)
class U8_3_Array(Array[U8, 3]): ...

arr = U8_3_Array([1, 2, 3])

# Encode: [elements...]
encoded = arr.encode()  # -> [01 02 03]

# Decode
decoded = U8_3_Array.decode(encoded)  # -> [1, 2, 3]

Bit Arrays

from jam.types.base.sequences import BitArray

# Create 8-bit array
@decodable_bit_array(8)
class Bit8Array(BitArray[8]): ...

bits = Bit8Array([1,0,1,0,1,0,1,0])

# Encode: packed bits
encoded = bits.encode()  # -> [AA]  # 10101010

# Decode
decoded = Bit8Array.decode(encoded)  # -> [1,0,1,0,1,0,1,0]

Dynamic Vectors

from jam.types.base.sequences import Vector
from jam.types.base.integers import U32

# Create vector of u32
@decodable_vector(U32)
class U32Vector(Vector[U32]): ...

vec = U32Vector([1, 2, 3])

# Encode: [len][elements...]
encoded = vec.encode()
# -> [03 01 00 00 00 02 00 00 00 03 00 00 00]

# Decode
decoded = U32Vector.decode(encoded)  # -> [1, 2, 3]

Byte Arrays

from jam.types.base.sequences import ByteArray32, Bytes

# Fixed size
fixed = ByteArray32(bytes([1] * 32))
encoded = fixed.encode()  # -> [01 01 ... 01] (32 bytes)

# Dynamic size
dynamic = Bytes(bytes([1, 2, 3]))
encoded = dynamic.encode()  # -> [03 01 02 03]

API Reference

Classes

class jam.types.base.sequences.array.Array(initial: Sequence[T] = [], codec: Codec[T] | None = None)[source]

Bases: BaseSequence, Generic[T]

Fixed-length array is an extension of the BaseSequence, to only allow fixed length arrays.

The array has a fixed length, append, extend, pop, insert, remove, and clear methods are not supported. Elements can be: - Set/Updated at any index - Swapped with another element at any index - Get from any index

__init__(initial: Sequence[T] = [], codec: Codec[T] | None = None)[source]

Initialize array.

Parameters:

initial – Required initial values

Raises:
  • TypeError – If elements are not all of the same Codable type

  • ValueError – If initial values don’t match fixed length

__setitem__(index: int | slice, value: T | Sequence[T]) None[source]

Set item at index or slice.

append(value: T) None[source]

Append value to end of vector.

Parameters:

value – Value to append. Must be instance of the same type as other elements.

Raises:

TypeError – If value is not of the correct type

pop(index: int = -1) T[source]

Remove and return item at index.

Parameters:

index – Index of item to remove

Returns:

Removed item

Raises:

IndexError – If index out of range

insert(index: int, value: T) None[source]

Insert value at index.

Parameters:
  • index – Index to insert at

  • value – Value to insert. Must be instance of the same type as other elements.

Raises:

TypeError – If value is not of the correct type

remove(value: T) None[source]

Remove first occurrence of value.

Parameters:

value – Value to remove

Raises:

ValueError – If value not found

clear() None[source]

Clear all elements.

extend(values: Sequence[T]) None[source]

Extend vector with values.

Parameters:

values – Values to add. Must all be instances of the same type as existing elements.

Raises:

TypeError – If values are not all of the correct type

class jam.types.base.sequences.vector.Vector(initial: Sequence[T] = [], codec: Codec[T] | None = None)[source]

Bases: BaseSequence[T]

Dynamic array implementation that supports codec operations.

The vector grows dynamically as elements are added. All standard sequence operations are supported. All elements must be instances of the same Codable type.

__init__(initial: Sequence[T] = [], codec: Codec[T] | None = None)[source]

Initialize sequence.

Parameters:
  • initial – Initial values

  • codec – Optional codec

class jam.types.base.sequences.bytes.bit_array.BitArray(value: int | bool | bytes | str | bytearray | memoryview | Sequence)[source]

Bases: Array

Fixed-length bit sequence implementation that supports codec operations.

A BitSequence represents a fixed-length sequence of bits, where each bit is represented as a Boolean value. The sequence is encoded as a compact bit array.

__init__(value: int | bool | bytes | str | bytearray | memoryview | Sequence)[source]

Initialize bit sequence.

Parameters:

value – Initial values. Must match the fixed length. All elements must be Boolean instances.

Raises:
  • TypeError – If elements are not Boolean instances

  • ValueError – If initial values don’t match fixed length

classmethod from_json(data: Any) BitArray[source]

Deserialize from JSON.

class jam.types.base.sequences.bytes.byte_array.ByteArray(value: int | bool | bytes | str | bytearray | memoryview | Sequence)[source]

Bases: Array[Byte]

Array of bytes

__init__(value: int | bool | bytes | str | bytearray | memoryview | Sequence)[source]

Initialize array.

Parameters:

initial – Required initial values

Raises:
  • TypeError – If elements are not all of the same Codable type

  • ValueError – If initial values don’t match fixed length

to_int(byteorder: Literal['big', 'little'] = 'big')[source]
classmethod from_json(data: Any) ByteArray[source]

Deserialize from JSON.

to_json() str[source]

Convert to JSON representation as hex string.

class jam.types.base.sequences.bytes.bytes.Bytes(value: int | bool | bytes | str | bytearray | memoryview | Sequence)[source]

Bases: Vector[Byte]

Variable-length byte sequence type.

__init__(value: int | bool | bytes | str | bytearray | memoryview | Sequence)[source]

Initialize Bytes.

Parameters:

value – Bytable which is either int, bytes, str, bytearray, memoryview, Sequence[Byte]

hex() str[source]

Get hex representation of Bytes.

classmethod from_json(data: Any) Bytes[source]

Create from JSON representation.

static decode_from(buffer: bytes | bytearray | memoryview, offset: int = 0) Tuple[Vector[T], int]

Decode from buffer. Must be implemented by subclasses or added via decorator.

Parameters:
  • buffer – Buffer to decode from

  • offset – Starting position in buffer

Returns:

  • The decoded value

  • Number of bytes read

Return type:

Tuple containing

Decorators

jam.types.base.sequences.array.decodable_array(length: int, element_type: Type[T]) Callable[[Type[Any]], Type[Any]][source]

Decorator that creates a fixed-length array type with a specific element type.

This decorator configures the array class with: 1. Fixed length 2. Element type validation 3. Custom decode_from implementation

jam.types.base.sequences.vector.decodable_vector(element_type: Type[T], max_length: int = 9223372036854775807) Callable[[Type[Vector[T]]], Type[Vector[T]]][source]

Decorator to make a class decodable as a vector.

jam.types.base.sequences.bytes.bit_array.decodable_bit_array(length: int, bitorder: Literal['msb', 'lsb'] | None = 'msb') Callable[[Type[BitArray]], Type[BitArray]][source]

Extend existing decodable_array to be array of Bits

Submodules