move MultiEnum to dotnet.util

This commit is contained in:
Shiz 2020-06-02 00:56:39 +02:00
parent 6f9ccf209b
commit d09a75fd93
4 changed files with 51 additions and 43 deletions

View File

@ -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_)
)

View File

@ -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
)

View File

@ -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

48
dotnet/util.py Normal file
View File

@ -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_)
)