Source code for jam.types.base.sequences.array

from typing import Generic, Sequence, Tuple, Type, TypeVar, Union, Callable, Any

from jam.utils.codec.codable import Codable
from jam.utils.codec.codec import Codec
from jam.utils.codec.composite.arrays import ArrayCodec
from .base import BaseSequence

T = TypeVar("T", bound=Codable)


[docs] class Array(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 """ _length: int = 0
[docs] def __init__(self, initial: Sequence[T] = [], codec: Codec[T] | None = None): """ Initialize array. Args: 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 """ if len(initial) != self._length: raise ValueError( f"Array: Initial values of length {len(initial)} must have length {self._length}" ) if codec is None: codec = ArrayCodec(self._length) super().__init__(initial=initial, codec=codec)
[docs] def __setitem__( self, index: Union[int, slice], value: Union[T, Sequence[T]] ) -> None: """Set item at index or slice.""" if isinstance(index, slice): # Get slice indices start, stop, step = index.indices(self._length) # Calculate length of slice slice_len = len(range(start, stop, step)) # If value is a single item, repeat it if not isinstance(value, Sequence): value = [value] * slice_len # Validate slice length matches value length if len(value) != slice_len: raise ValueError( f"Slice length {slice_len} does not match value length {len(value)}" ) # Set each value in slice for i, v in zip(range(start, stop, step), value): self._validate_value(v) self.value[i] = v else: if not 0 <= index < self._length: raise IndexError(f"Array: Index {index} out of range") self._validate_value(value) self.value[index] = value
[docs] def append(self, value: T) -> None: raise ValueError("Cannot append to fixed-length array")
[docs] def pop(self, index: int = -1) -> T: raise ValueError("Cannot pop from fixed-length array")
[docs] def insert(self, index: int, value: T) -> None: raise ValueError("Cannot insert into fixed-length array")
[docs] def remove(self, value: T) -> None: raise ValueError("Cannot remove from fixed-length array")
[docs] def clear(self) -> None: raise ValueError("Cannot clear fixed-length array")
[docs] def extend(self, values: Sequence[T]) -> None: raise ValueError("Cannot extend fixed-length array")
[docs] def decodable_array( length: int, element_type: Type[T] ) -> Callable[[Type[Any]], Type[Any]]: """ 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 """ def decorator(cls: Type[Array[T]]) -> Type[Array[T]]: cls._element_type = element_type cls._length = length @staticmethod def decode_from( buffer: Union[bytes, bytearray, memoryview], offset: int = 0 ) -> Tuple[Any, int]: value, size = ArrayCodec.decode_from(length, element_type, buffer, offset) return cls(value), size cls.decode_from = decode_from return cls return decorator