Base Types
Core data type implementations with binary encoding capabilities.
Type Implementations
Integers (
integers): * Fixed-width unsigned integers: U8, U16, U32, U64 (little-endian) * Signed integers: I8, I16, I32, I64 (little-endian) * Variable-width unsigned integers: Int (compact encoding for values < 2⁶⁴)Sequences (
sequences): * Fixed-length arrays: Array[T, N]- BitArray[Bit, N]: Fixed size packed bits
Byte[Bit,8]: 8-bit array
ByteArray[Bytes, N]: Fixed-length byte array
- Dynamic vectors: Vector[T]
Bytes: Variable length byte array
Containers: * Dictionary[K, V]: ordered key-value pairs * Choice[T]: discriminated union * Option[T]: nullable values
Basic Types: * Bit: single bit * String: UTF-8 with length prefix * Boolean: single byte (0/1) * Null: zero-sized type
Encoding Formats
Fixed-width Integer:
I32(42) -> [2A 00 00 00] # Little-endian
Variable-width Integer:
Int(42) -> [2A] # Single byte for small values
Int(1000) -> [E8 07] # Two bytes for larger values
String:
String("abc") -> [03 61 62 63] # Length prefix + UTF-8 bytes
Vector:
Vector[u8]([1,2]) -> [02 01 02] # Length prefix + elements
Dictionary:
Dict{"a": 1} -> [01 01 61 01] # Size + (key_len + key + value)...
Technical Details
- Memory Layout:
All types are packed (no padding)
Explicit alignment when needed
Direct buffer manipulation
Zero-copy where possible
- Type Parameters:
Generic over element types
Proper variance annotations
Compile-time size checks
Runtime validation
- Error Handling:
Range validation for integers
UTF-8 validation for strings
Buffer overflow checks
Type mismatch detection
Examples
Integer types:
from jam.types.base.integers import Int32, VarInt
# Fixed-width
value = I32(42)
assert value.encode() == bytes([42, 0, 0, 0])
# Variable-width
value = Int(1000)
assert value.encode() == bytes([232, 7]) # 0xE8 0x07
Sequence types:
from jam.types.base.sequences import Vector
from jam.types.base.integers import Int8
# Create I32 vector
@decodable_vector(I32)
class I32Vector(Vector[I32]): ...
vec = I32Vector([1, 2, 3])
# Encode: [len: varint][items: [u8; len]]
encoded = vec.encode()
assert encoded == bytes([3, 1, 2, 3])
# Decode
decoded, size = I32Vector.decode_from(encoded)
assert decoded == [1, 2, 3]
assert size == 4 # Total bytes read
Container types:
from jam.types.base.dictionary import Dict
from jam.types.base.string import String
from jam.types.base.integers import Int8
# Create dictionary of String keys and Int8 values
@decodable_dictionary(String, Int8)
class StringInt8Dict(Dict[String, Int8]): ...
d = StringInt8Dict({
"a": 1,
"b": 2
})
# Encode: [size][key_len key value]...
encoded = d.encode()
# Decode
decoded, _ = StringInt8Dict.decode_from(encoded)
assert decoded == {"a": 1, "b": 2}
API Reference
- Integer Types:
U8, U16, … U256: Fixed-width unsigned integers
I8, I16, … I256: Fixed-width signed integers
Int: Variable-width unsigned integer
- Sequence Types:
- Array[T, N]: Fixed-length array
- BitField[Bit, N]: Fixed size packed bits
Byte[Bit,8]: 8-bit array
ByteArray[Bytes, N]: Fixed-length byte array
- Vector[T]: Dynamic array
Bytes: Variable length byte array
- Choice Types:
Choice[T]: Tagged union
Option[T]: Optional value
- Container Types:
Dict[K, V]: Key-value mapping
- Basic Types:
String: UTF-8 string
Boolean: True/False
Null: Unit type
Submodules
Module Contents
- class jam.types.base.Int(value: int | BaseInteger)[source]
Bases:
BaseInteger,Codable- __init__(value: int | BaseInteger)[source]
Initialize an integer.
- static decode_from(buffer: bytes | bytearray | memoryview, offset: int = 0) Tuple[Any, int][source]
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
- class jam.types.base.U8(value: int | BaseInteger)[source]
Bases:
FixedInt- static decode_from(buffer: bytes | bytearray | memoryview, offset: int = 0) Tuple[Any, 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
- has_sign = False
- class jam.types.base.U16(value: int | BaseInteger)[source]
Bases:
FixedInt- static decode_from(buffer: bytes | bytearray | memoryview, offset: int = 0) Tuple[Any, 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
- has_sign = False
- class jam.types.base.U32(value: int | BaseInteger)[source]
Bases:
FixedInt- static decode_from(buffer: bytes | bytearray | memoryview, offset: int = 0) Tuple[Any, 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
- has_sign = False
- class jam.types.base.U64(value: int | BaseInteger)[source]
Bases:
FixedInt- static decode_from(buffer: bytes | bytearray | memoryview, offset: int = 0) Tuple[Any, 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
- has_sign = False
- class jam.types.base.U128(value: int | BaseInteger)[source]
Bases:
FixedInt- static decode_from(buffer: bytes | bytearray | memoryview, offset: int = 0) Tuple[Any, 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
- has_sign = False
- class jam.types.base.U256(value: int | BaseInteger)[source]
Bases:
FixedInt- static decode_from(buffer: bytes | bytearray | memoryview, offset: int = 0) Tuple[Any, 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
- has_sign = False
- class jam.types.base.U512(value: int | BaseInteger)[source]
Bases:
FixedInt- static decode_from(buffer: bytes | bytearray | memoryview, offset: int = 0) Tuple[Any, 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
- has_sign = False
- class jam.types.base.Choice(initial: Dict[str, Codable[T]] | Codable[T])[source]
Bases:
Codable[T],JsonSerde,Generic[T]A choice is a value that can be one of several possible types.
A Choice represents a tagged union type that can hold a value of one of several possible Codable types. The actual type is determined by a tag byte during encoding/decoding.
- To use a choice, you need to define all possible types:
>>> @decodable_choice([U8, U16]) >>> class MyChoice(Choice): ... >>> my_choice: MyChoice = MyChoice(U8(1)) >>> assert my_choice.type == U8 >>> assert my_choice.value == U8(1)
- To use a optional choice, we’d pair it with Nullable:
>>> @decodable_choice([U8, Nullable]) >>> class OptionalU8(Choice): ... >>> my_choice: OptionalU8 = OptionalU8(U8(1)) >>> assert my_choice.type == U8 >>> assert my_choice.value == U8(1) >>> my_choice: OptionalU8 = OptionalU8(Null) >>> assert my_choice.type == Nullable >>> assert my_choice.value is None
- To use this as an enum:
>>> @decodable_choice([String, String, String]) >>> class OutputType(Choice): ...
- __init__(initial: Dict[str, Codable[T]] | Codable[T])[source]
Initialize Choice.
- Parameters:
initial – Mapping of initial choice name and its value. Should have only one key.
- Raises:
ValueError – If types list is empty
- __set_internal__(value: Dict[str, Codable[T]] | Codable[T]) None[source]
Set the choice value.
- Parameters:
value – Value to set. Must be instance of one of the allowed types.
- Raises:
ValueError – If value type is not in allowed types list
- class jam.types.base.Option(initial: Codable = Null)[source]
Bases:
ChoiceAn option is a choice that can be either None or a value.
- __init__(initial: Codable = Null)[source]
Initialize Choice.
- Parameters:
initial – Mapping of initial choice name and its value. Should have only one key.
- Raises:
ValueError – If types list is empty
- class jam.types.base.Nullable[source]
-
Null value implementation.
A Null represents the absence of a value. It is encoded as an empty byte sequence.
Examples
>>> null = Null() >>> encoded = null.encode() >>> assert encoded == b"" >>> decoded, size = Null.decode_from(encoded) >>> assert decoded == null >>> assert size == 0
- class jam.types.base.Dictionary(initial: Mapping[K, V] | None = None)[source]
Bases:
Generic[K,V],Codable,Mapping[K,V],JsonSerdeDictionary implementation that supports codec operations.
A dictionary that maps Codable keys to Codable values, providing both standard dictionary operations and codec functionality for serialization/deserialization.
Examples
>>> from jam.types.base.string import String >>> from jam.types.base.integers import Int >>> d = Dictionary({String("key"): Int(42)}) >>> d[String("key")] Int(42) >>> encoded = d.encode() >>> decoded, _ = Dictionary.decode_from(String, Int, encoded) >>> decoded == d True
- __init__(initial: Mapping[K, V] | None = None)[source]
Initialize dictionary.
- Parameters:
initial – Optional initial key-value pairs
- Raises:
TypeError – If any key or value is not Codable
- get(key: K, default: V | None = None) V | None[source]
Get value for key, returning default if key not found.
- Parameters:
key – Key to look up
default – Value to return if key not found
- Returns:
Value for key or default
- values() ValuesView[V][source]
Get view of values.
- class jam.types.base.Boolean(value: bool)[source]
-
Boolean type that implements the Codable interface.
Examples
>>> b = Boolean(True) >>> bool(b) True >>> b.encode() b'\x01' >>> Boolean.decode_from(b'\x01') (Boolean(True), 1)
- class jam.types.base.Bit(value: int | bool | bytes | str | bytearray | memoryview | Sequence)[source]
Bases:
JsonSerdeA bit is a single binary digit, either 0 or 1.
- class jam.types.base.String(value: str)[source]
-
UTF-8 encoded string type that implements the Codable interface.
Examples
>>> s = String("Hello") >>> str(s) 'Hello' >>> len(s) 5 >>> s.encode() b'\x05Hello' # Length prefix followed by UTF-8 bytes
Note
String length is measured in UTF-16 code units, which means some Unicode characters (like emojis) may count as 2 units. This matches Python’s string length behavior.
- __init__(value: str)[source]
Initialize a string.
- Parameters:
value – Python string value
- Raises:
TypeError – If value is not a str
- static decode_from(buffer: bytes | bytearray | memoryview, offset: int = 0) Tuple[String, int][source]
Decode a String from a buffer.
- Parameters:
buffer – Bytes to decode from
offset – Starting position in buffer
- Returns:
Tuple of (String instance, bytes read)
- Raises:
ValueError – If buffer is too short
UnicodeDecodeError – If buffer contains invalid UTF-8
- class jam.types.base.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
- 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
- class jam.types.base.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.
- class jam.types.base.ByteArray8(value: int | bool | bytes | str | bytearray | memoryview | Sequence)[source]
Bases:
ByteArray- static decode_from(buffer: bytes | bytearray | memoryview, offset: int = 0) Tuple[Any, 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
- class jam.types.base.ByteArray16(value: int | bool | bytes | str | bytearray | memoryview | Sequence)[source]
Bases:
ByteArray- static decode_from(buffer: bytes | bytearray | memoryview, offset: int = 0) Tuple[Any, 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
- class jam.types.base.ByteArray32(value: int | bool | bytes | str | bytearray | memoryview | Sequence)[source]
Bases:
ByteArray- static decode_from(buffer: bytes | bytearray | memoryview, offset: int = 0) Tuple[Any, 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
- class jam.types.base.ByteArray64(value: int | bool | bytes | str | bytearray | memoryview | Sequence)[source]
Bases:
ByteArray- static decode_from(buffer: bytes | bytearray | memoryview, offset: int = 0) Tuple[Any, 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
- class jam.types.base.ByteArray96(value: int | bool | bytes | str | bytearray | memoryview | Sequence)[source]
Bases:
ByteArray- static decode_from(buffer: bytes | bytearray | memoryview, offset: int = 0) Tuple[Any, 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
- class jam.types.base.ByteArray128(value: int | bool | bytes | str | bytearray | memoryview | Sequence)[source]
Bases:
ByteArray- static decode_from(buffer: bytes | bytearray | memoryview, offset: int = 0) Tuple[Any, 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
- class jam.types.base.ByteArray144(value: int | bool | bytes | str | bytearray | memoryview | Sequence)[source]
Bases:
ByteArray- static decode_from(buffer: bytes | bytearray | memoryview, offset: int = 0) Tuple[Any, 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
- class jam.types.base.ByteArray256(value: int | bool | bytes | str | bytearray | memoryview | Sequence)[source]
Bases:
ByteArray- static decode_from(buffer: bytes | bytearray | memoryview, offset: int = 0) Tuple[Any, 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
- class jam.types.base.ByteArray784(value: int | bool | bytes | str | bytearray | memoryview | Sequence)[source]
Bases:
ByteArray- static decode_from(buffer: bytes | bytearray | memoryview, offset: int = 0) Tuple[Any, 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
- class jam.types.base.BitArray(value: int | bool | bytes | str | bytearray | memoryview | Sequence)[source]
Bases:
ArrayFixed-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
- class jam.types.base.Byte(value: int | bool | bytes | str | bytearray | memoryview | Sequence)[source]
Bases:
BitArrayA single byte value that supports codec operations. Array uses BitSequenceCodec.
A Byte represents an 8-bit array that is encoded as a single byte.
- static decode_from(buffer: bytes | bytearray | memoryview, offset: int = 0) Tuple[BitArray, 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
- class jam.types.base.Bytes(value: int | bool | bytes | str | bytearray | memoryview | Sequence)[source]
-
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]
- 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
- jam.types.base.decodable_int(byte_size: int, has_sign=False) Callable[[Type[FixedInt]], Type[FixedInt]][source]
Decorator to make a class decodable as an integer.
- jam.types.base.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.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
- jam.types.base.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.