import struct
from typing import (
Any,
Self,
TYPE_CHECKING,
)
if TYPE_CHECKING:
from .page import (
PfPage,
)
from abc import (
ABC,
)
from .error import (
PfUnpinnedPageManipulationError,
)
__all__ = (
'PfLayoutField',
'PfLayoutView',
)
[문서]
class PfLayoutField:
"""
layout view의 field를 나타내는 클래스입니다.
Attributes:
name (str):
field의 이름.
format (str):
field의 format (`struct` 모듈에서 사용하는 format).
offset (int):
field의 오프셋.
size (int):
field의 크기.
`struct.calcsize(format)` 를 사용하여 계산됩니다.
"""
[문서]
def __init__(self, name: str, format: str) -> None:
"""
field를 초기화합니다.
Args:
name (str):
field의 이름.
format (str):
field의 format (`struct` 모듈에서 사용하는 format).
"""
self.name = name
self.format = format
self.offset = -1
self.size = struct.calcsize(format)
[문서]
class PfLayoutView(ABC):
SIZE: int
"""
layout view의 크기.
"""
_fields: tuple[PfLayoutField, ...]
_field_table: dict[str, PfLayoutField]
def __init_subclass__(cls: type[Self]) -> None:
offset = 0
cls._field_table = {}
for field in cls._fields:
cls._field_table[field.name] = field
field.offset = offset
offset += field.size
cls.SIZE = offset
[문서]
def __init__(self,
page: 'PfPage',
offset: int,
limit: int,
) -> None:
"""
layout view를 초기화합니다.
Args:
page (PfPage):
대상 page.
offset (int):
page data 중 layout view가 바라보는 부분의 오프셋.
limit (int):
page data 중 layout view가 바라보는 부분의 크기.
"""
self._page = page
self._view = memoryview(page.data)[offset: offset + limit]
[문서]
def get(self, name: str) -> Any:
if not self._page.is_pinned():
raise PfUnpinnedPageManipulationError(
"page가 pin 되어있지 않습니다 "
f"(대상 페이지: {self._page.pid}).",
)
field = self._field_table[name]
data = self._view[field.offset: field.offset + field.size]
(value,) = struct.unpack(field.format, data)
return value
[문서]
def set(self, name: str, value: Any) -> None:
if not self._page.is_pinned():
raise PfUnpinnedPageManipulationError(
"page가 pin 되어있지 않습니다 "
f"(대상 페이지: {self._page.pid}).",
)
field = self._field_table[name]
data = struct.pack(field.format, value)
self._view[field.offset: field.offset + field.size] = data
self._page.mark_dirty()