Исходный код bytespec.codecs.list

# Copyright (c) 2026 ink-developer

from typing import Any

from typing_extensions import override

from bytespec.codecs import ICodec
from bytespec.enums import ByteOrder
from bytespec.errors import SchemaError
from bytespec.models import PrefixLength

from ._utils import check_available
from .map import UINT_CODEC_MAPPING


[документация] class ListCodec(ICodec[list[Any]]): """A list prefixed with the total size of its encoded items in bytes. Args: item_codec: The codec for a single item. When reading, it must advance offset by a positive number of bytes within the supplied buffer. prefix_length: Prefix size: 1, 2, 4, or 8 bytes, or ``VarUInt``. Defaults to 4 bytes. The prefix does not store the item count. Raises: SchemaError: Unsupported length prefix. """ def __init__(self, item_codec: ICodec[Any], prefix_length: PrefixLength = 4) -> None: self.item_codec = item_codec self.prefix_length = prefix_length codec = UINT_CODEC_MAPPING.get(prefix_length) if codec is None: raise SchemaError(f"ListCodec: invalid length prefix {prefix_length!r}") self.codec = codec @override def encode(self, data: list[Any], byte_order: ByteOrder) -> bytes: """Write consecutive items prefixed with their total byte length. Raises: EncodeError: The size does not fit in the prefix, or an item cannot be encoded by the selected codec. """ payload = bytearray() for value in data: payload.extend(self.item_codec.encode(value, byte_order)) return self.codec.encode(len(payload), byte_order) + payload @override def decode(self, buffer: bytes, byte_order: ByteOrder, offset: int) -> tuple[list[Any], int]: """Read a list and return it with its absolute end offset. Items are read from a separate buffer containing the list contents; offsets in their errors refer to that buffer. Raises: DecodeError: The prefix or data is incomplete, or the item codec rejected the data. ValueError: Negative offset. """ length, start = self.codec.decode(buffer, byte_order, offset) end = start + length check_available(buffer, start, length, codec=type(self).__name__) values = buffer[start:end] data = [] item_offset = 0 while item_offset < len(values): value, item_offset = self.item_codec.decode(values, byte_order, item_offset) data.append(value) return data, end