feat: add ListField
This commit is contained in:
parent
2149fcf308
commit
7e8b57793f
3 changed files with 42 additions and 0 deletions
|
|
@ -3,6 +3,7 @@ from .bool import BoolField
|
||||||
from .field import Field
|
from .field import Field
|
||||||
from .float import FloatField
|
from .float import FloatField
|
||||||
from .int import IntField
|
from .int import IntField
|
||||||
|
from .list import ListField
|
||||||
from .str import StrField
|
from .str import StrField
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
|
|
@ -11,5 +12,6 @@ __all__ = [
|
||||||
"BoolField",
|
"BoolField",
|
||||||
"FloatField",
|
"FloatField",
|
||||||
"IntField",
|
"IntField",
|
||||||
|
"ListField",
|
||||||
"StrField",
|
"StrField",
|
||||||
]
|
]
|
||||||
|
|
|
||||||
38
src/snakia/field/list.py
Normal file
38
src/snakia/field/list.py
Normal file
|
|
@ -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
|
||||||
|
|
@ -4,6 +4,7 @@ from .bool import BoolField as bool
|
||||||
from .field import Field as field
|
from .field import Field as field
|
||||||
from .float import FloatField as float
|
from .float import FloatField as float
|
||||||
from .int import IntField as int
|
from .int import IntField as int
|
||||||
|
from .list import ListField as list
|
||||||
from .str import StrField as str
|
from .str import StrField as str
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
|
|
@ -12,5 +13,6 @@ __all__ = [
|
||||||
"field",
|
"field",
|
||||||
"float",
|
"float",
|
||||||
"int",
|
"int",
|
||||||
|
"list",
|
||||||
"str",
|
"str",
|
||||||
]
|
]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue