move MultiEnum to dotnet.util
This commit is contained in:
parent
6f9ccf209b
commit
d09a75fd93
|
@ -1,6 +1,5 @@
|
|||
import enum
|
||||
import math
|
||||
import collections
|
||||
from destruct import Type, Struct
|
||||
|
||||
class CLIStreamType(enum.Enum):
|
||||
|
@ -187,43 +186,3 @@ class CLIStreamIndex(Type):
|
|||
else:
|
||||
size = 2
|
||||
return int.from_bytes(input.read(size), 'little')
|
||||
|
||||
class MultiEnumMeta(type):
|
||||
@classmethod
|
||||
def __prepare__(mcls, name, bases, **kwargs):
|
||||
return collections.OrderedDict()
|
||||
|
||||
def __new__(cls, name, bases, attrs, **kwargs):
|
||||
parsers = {}
|
||||
used = 0
|
||||
for key, value in attrs.copy().items():
|
||||
if isinstance(value, tuple):
|
||||
if len(value) == 2:
|
||||
child, mask = value
|
||||
elif len(value) == 3:
|
||||
child, offset, size = value
|
||||
mask = ((1 << size) - 1) << offset
|
||||
if issubclass(child, enum.Enum):
|
||||
if mask is None:
|
||||
mask = ~used
|
||||
parsers[key] = (child, mask)
|
||||
used |= mask
|
||||
del attrs[key]
|
||||
|
||||
attrs['_parsers_'] = parsers
|
||||
return super().__new__(cls, name, bases, attrs)
|
||||
|
||||
class MultiEnum(metaclass=MultiEnumMeta):
|
||||
def __init__(self, value: int):
|
||||
for field, (child, mask) in self._parsers_.items():
|
||||
setattr(self, field, child(value & mask))
|
||||
|
||||
def __str__(self):
|
||||
return '{}({})'.format(self.__class__.__name__,
|
||||
', '.join('{}: {}'.format(n, getattr(self, n)) for n in self._parsers_)
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
return '<{}({})>'.format(self.__class__.__name__,
|
||||
', '.join('{}: {!r}'.format(n, getattr(self, n)) for n in self._parsers_)
|
||||
)
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import enum
|
||||
from destruct import Struct
|
||||
|
||||
from .util import MultiEnum
|
||||
from .common import (
|
||||
MultiEnum,
|
||||
CLIElementType, CLIStreamType, CLITableType,
|
||||
CLICodedToken, CLIStreamIndex, CLITableIndex, CLITableRange
|
||||
)
|
||||
|
|
|
@ -2,7 +2,8 @@ import enum
|
|||
from itertools import zip_longest
|
||||
|
||||
from destruct import parse, Type, Struct
|
||||
from .common import CLICodedToken, CLITableType, CLIElementType, MultiEnum
|
||||
from .util import MultiEnum
|
||||
from .common import CLICodedToken, CLITableType, CLIElementType
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
import inspect
|
||||
import collections
|
||||
import functools
|
||||
|
||||
|
||||
def cached_property(f):
|
||||
return property(functools.lru_cache()(f))
|
||||
|
||||
|
||||
class MultiEnumMeta(type):
|
||||
@classmethod
|
||||
def __prepare__(mcls, name, bases, **kwargs):
|
||||
return collections.OrderedDict()
|
||||
|
||||
def __new__(cls, name, bases, attrs, **kwargs):
|
||||
parsers = {}
|
||||
used = 0
|
||||
for key, value in attrs.copy().items():
|
||||
if isinstance(value, tuple):
|
||||
if len(value) == 2:
|
||||
child, mask = value
|
||||
elif len(value) == 3:
|
||||
child, offset, size = value
|
||||
mask = ((1 << size) - 1) << offset
|
||||
if inspect.isclass(child):
|
||||
if mask is None:
|
||||
mask = ~used
|
||||
parsers[key] = (child, mask)
|
||||
used |= mask
|
||||
del attrs[key]
|
||||
|
||||
attrs['_parsers_'] = parsers
|
||||
return super().__new__(cls, name, bases, attrs)
|
||||
|
||||
class MultiEnum(metaclass=MultiEnumMeta):
|
||||
def __init__(self, value: int):
|
||||
for field, (child, mask) in self._parsers_.items():
|
||||
setattr(self, field, child(value & mask))
|
||||
|
||||
def __str__(self):
|
||||
return '{}({})'.format(self.__class__.__name__,
|
||||
', '.join('{}: {}'.format(n, getattr(self, n)) for n in self._parsers_)
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
return '<{}({})>'.format(self.__class__.__name__,
|
||||
', '.join('{}: {!r}'.format(n, getattr(self, n)) for n in self._parsers_)
|
||||
)
|
Loading…
Reference in New Issue