Base Types

Core data type implementations with binary encoding capabilities.

Type Implementations

  1. 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⁶⁴)

  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

  3. Containers: * Dictionary[K, V]: ordered key-value pairs * Choice[T]: discriminated union * Option[T]: nullable values

  4. 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.

_validate(value: int) None[source]

Validate the integer value is within bounds.

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

byte_size: int = 1
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

byte_size: int = 2
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

byte_size: int = 4
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

byte_size: int = 8
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

byte_size: int = 16
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

byte_size: int = 32
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

byte_size: int = 64
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

__get__() Codable[T] | None[source]

Get the current value.

Returns:

Current value or None if not set

__eq__(other: object) bool[source]

Compare for equality.

__bool__() bool[source]

Check if the choice has a value.

__repr__() str[source]

Get string representation.

classmethod from_json(data: Any) Choice[T][source]

Create from JSON representation.

class jam.types.base.Option(initial: Codable = Null)[source]

Bases: Choice

An 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

static option_to_choice(value: Codable | Nullable) Dict[str, Codable][source]
classmethod from_json(data: Any) Option[source]

Create from JSON representation.

to_json() Any[source]

Convert to JSON representation.

class jam.types.base.Nullable[source]

Bases: Codable, JsonSerde

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
__init__()[source]

Initialize Null value.

get() None[source]

Get the null value.

Returns:

None

__repr__() str[source]

Get string representation.

__eq__(other: object) bool[source]

Compare for equality.

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

Decode null value from buffer.

Parameters:
  • buffer – Source buffer

  • offset – Starting offset

Returns:

Tuple of (decoded null value, bytes read)

to_json() None[source]

Convert to JSON representation.

classmethod from_json(data: Any) Nullable[source]

Create from JSON representation.

class jam.types.base.Dictionary(initial: Mapping[K, V] | None = None)[source]

Bases: Generic[K, V], Codable, Mapping[K, V], JsonSerde

Dictionary 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
key_type: Type[K]
value_type: Type[V]
__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

__getitem__(key: K) V[source]

Get value for key.

__iter__() Iterator[K][source]

Iterate over keys.

__len__() int[source]

Get number of items.

__eq__(other: object) bool[source]

Compare for equality.

__repr__() str[source]

Get string representation.

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

items() ItemsView[K, V][source]

Get view of (key, value) pairs.

keys() KeysView[K][source]

Get view of keys.

values() ValuesView[V][source]

Get view of values.

to_json() Dict[Any, Any][source]

Convert to JSON representation.

classmethod from_json(data: Dict[Any, Any] | Sequence[Any]) Self[source]

Create instance from JSON representation.

class jam.types.base.Boolean(value: bool)[source]

Bases: Codable, JsonSerde

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)
__init__(value: bool)[source]

Initialize a Boolean.

Parameters:

value – Python bool value

Raises:

TypeError – If value is not a bool

__bool__() bool[source]

Allow using in boolean context.

__eq__(other: Any) bool[source]

Equal comparison.

__hash__() int[source]

Make hashable.

__repr__() str[source]

String representation.

__bytes__() bytes[source]

Bytes representation.

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

Decode a Boolean from a buffer.

Parameters:
  • buffer – Bytes to decode from

  • offset – Starting position in buffer

Returns:

Tuple of (Boolean instance, bytes read)

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

Bases: JsonSerde

A bit is a single binary digit, either 0 or 1.

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

Convert to JSON representation.

classmethod from_json(value: Any) Bit[source]

Create from JSON representation.

class jam.types.base.String(value: str)[source]

Bases: Codable, JsonSerde

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

__str__() str[source]

Convert to str.

__len__() int[source]

Get string length in UTF-16 code units.

__getitem__(index: int | slice) str[source]

Get character(s) at index or slice.

__contains__(item: str) bool[source]

Check if string contains substring.

__eq__(other: Any) bool[source]

Compare for equality.

__hash__() int[source]

Make hashable.

__add__(other: String | str) String[source]

Concatenate strings.

__repr__() str[source]

Get string representation.

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:
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

__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.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.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: 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.Byte(value: int | bool | bytes | str | bytearray | memoryview | Sequence)[source]

Bases: BitArray

A 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]

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

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.

jam.types.base.decodable_dictionary(key_type: Type[K], value_type: Type[V]) Type[Dictionary[K, V]][source]
jam.types.base.decodable_choice(cls: Type[Choice]) Type[Choice][source]
jam.types.base.decodable_option(optional_type: Type[Codable]) Type[Option][source]

Decodable choice