sx/sx/core/meta.py

88 lines
2.8 KiB
Python

from typing import Optional as O, Generic as G, Sequence, TypeVar, Any
from .base import Type, Context, PathElement, Error
from .io import Stream
from . import to_type
T = TypeVar('T')
class Wrapper(G[T], Type[T]):
def __init__(self, child: Type[T]) -> None:
self.child = child
def parse(self, context: Context, stream: Stream) -> T:
return context.parse(to_type(self.child), stream)
def dump(self, context: Context, stream: Stream, value: O[T]) -> None:
context.dump(to_type(self.child), stream, value)
def sizeof(self, context: Context, value: O[T]) -> O[int]:
return context.sizeof(to_type(self.child), value)
def offsetof(self, context: Context, path: Sequence[PathElement], value: O[T]) -> O[int]:
return context.offsetof(to_type(self.child), path, value)
def default(self, context: Context) -> T:
return context.default(to_type(self.child))
def __str__(self) -> str:
return str(self.child)
def __repr__(self) -> str:
return repr(self.child)
class Generic(Type):
__slots__ = ('name', 'stack')
def __init__(self, name: str) -> None:
self.name = name
self.stack = []
def push(self, value: Any) -> None:
if isinstance(value, Generic):
self.stack.append(value.stack[-1])
else:
self.stack.append(value)
def pop(self) -> None:
self.stack.pop()
def _get_sx_type_(self, ident: Any) -> Type:
return to_type(self.stack[-1])
def parse(self, context: Context, stream: Stream) -> Any:
if not self.stack:
raise Error(context, 'unresolved generic')
return context.parse(to_type(self.stack[-1]), stream)
def dump(self, context: Context, stream: Stream, value: O[Any]) -> None:
if not self.stack:
raise Error(context, 'unresolved generic')
context.dump(to_type(self.stack[-1]), stream, value)
def sizeof(self, context: Context, value: O[Any]) -> O[int]:
if not self.stack:
return None
return context.sizeof(to_type(self.stack[-1]), value)
def offsetof(self, context: Context, path: Sequence[PathElement], value: O[Any]) -> O[int]:
if not self.stack:
return None
return context.offsetof(to_type(self.stack[-1]), path, value)
def default(self, context: Context) -> Any:
if not self.stack:
raise Error(context, 'unresolved generic')
return context.default(to_type(self.stack[-1]))
def __str__(self) -> str:
if self.stack:
return f'${self.name}:{to_type(self.stack[-1])}'
return f'${self.name}:unresolved'
def __repr__(self) -> str:
return f'<{__name__}.{self.__class__.__name__}({self.stack!r})>'
def __deepcopy__(self, memo: Any) -> Any:
return self