From 7e8b57793f18cda69936825cf69703763cabd24b Mon Sep 17 00:00:00 2001 From: rus07tam Date: Wed, 26 Nov 2025 14:02:48 +0000 Subject: [PATCH] feat: add ListField --- src/snakia/field/__init__.py | 2 ++ src/snakia/field/list.py | 38 ++++++++++++++++++++++++++++++++++++ src/snakia/field/t.py | 2 ++ 3 files changed, 42 insertions(+) create mode 100644 src/snakia/field/list.py diff --git a/src/snakia/field/__init__.py b/src/snakia/field/__init__.py index 654fdd9..752b06e 100644 --- a/src/snakia/field/__init__.py +++ b/src/snakia/field/__init__.py @@ -3,6 +3,7 @@ from .bool import BoolField from .field import Field from .float import FloatField from .int import IntField +from .list import ListField from .str import StrField __all__ = [ @@ -11,5 +12,6 @@ __all__ = [ "BoolField", "FloatField", "IntField", + "ListField", "StrField", ] diff --git a/src/snakia/field/list.py b/src/snakia/field/list.py new file mode 100644 index 0000000..f2671da --- /dev/null +++ b/src/snakia/field/list.py @@ -0,0 +1,38 @@ +from typing import Callable, Final, Iterable, TypeVar + +from typing_extensions import Self + +from .field import Field + +T = TypeVar("T") + + +class ListField(Field[list[T]]): + def __init__( + self, + field: Field[T], + *, + length_size: int = 1, + default_factory: Callable[[Self], Iterable[T]] = lambda _: (), + ) -> None: + self.length_size: Final[int] = length_size + self.field: Final = field + super().__init__(default_factory=lambda s: [*default_factory(s)]) + + def serialize(self, items: list[T], /) -> bytes: + result = b"" + for item in items: + value = self.field.serialize(item) + length_prefix = len(value).to_bytes(self.length_size, "big") + result += length_prefix + value + return result + + def deserialize(self, serialized: bytes, /) -> list[T]: + result = [] + while serialized: + length = int.from_bytes(serialized[: self.length_size], "big") + serialized = serialized[self.length_size :] + item = self.field.deserialize(serialized[:length]) + serialized = serialized[length:] + result.append(item) + return result diff --git a/src/snakia/field/t.py b/src/snakia/field/t.py index f535738..64cf5a7 100644 --- a/src/snakia/field/t.py +++ b/src/snakia/field/t.py @@ -4,6 +4,7 @@ from .bool import BoolField as bool from .field import Field as field from .float import FloatField as float from .int import IntField as int +from .list import ListField as list from .str import StrField as str __all__ = [ @@ -12,5 +13,6 @@ __all__ = [ "field", "float", "int", + "list", "str", ]