Microsoft Common Language Infrastructure (also known as .NET) metadata parser
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

48 lines
1.5 KiB

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
shift = 0
elif len(value) == 3:
child, mask, shift = value
if inspect.isclass(child):
if mask is None:
mask = ~used
parsers[key] = (child, mask, shift)
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, shift) in self._parsers_.items():
setattr(self, field, child((value & mask) >> shift))
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_)
)