Source code for scrutiny.core.embedded_enum

#    embedded_enum.py
#        Contains the definition for an enum on the embedded side
#
#   - License : MIT - See LICENSE file
#   - Project : Scrutiny Debugger (github.com/scrutinydebugger/scrutiny-main)
#
#    Copyright (c) 2024 Scrutiny Debugger

__all__ = ['EmbeddedEnum', 'EmbeddedEnumDef']

from scrutiny.tools.typing import *


class EmbeddedEnumDef(TypedDict):
    """
    Represent the dictionary version of the EmbeddedEnum (for .json import/export).
    Used only for type hints
    """
    name: str
    values: Dict[str, int]


[docs] class EmbeddedEnum: """ Represents an enumeration in the embedded code. Match a string to an int value """ name: str vals: Dict[str, int] def __eq__(self, other: Any) -> bool: if not isinstance(other, EmbeddedEnum): return False if self.name != other.name: return False if self.vals != other.vals: return False return True def __hash__(self) -> int: items = list(self.vals.items()) items.sort(key=lambda x: x[0]) h = hash(self.name) for k, v in items: h ^= hash(k) h ^= hash(v) return h def __init__(self, name: str, vals: Optional[Dict[str, int]] = None): self.name = name self.vals = {} if vals is not None: for k, v in vals.items(): self.add_value(k, v) def __repr__(self) -> str: return f'<{self.__class__.__name__} "{self.name}" ({len(self.vals)} values) at 0x{id(self):08x}>'
[docs] def get_first_value_name_match(self, wanted_val: int) -> Optional[str]: """Return the name associated with a value. In case of duplicates, the first found is returned. :param wanted_val: The numerical value to search for """ for name, val in self.vals.items(): if val == wanted_val: return name return None
[docs] def add_value(self, name: str, value: int) -> None: """Adds a string/value pair in the enum :param name: Enumerator name :param value: Enumerator value :raises IndexError: If the enumerator name is already defined in the enum with a different value """ if name in self.vals and self.vals[name] != value: raise IndexError('Duplicate entry for enum %s. %s can either be %s or %s' % (self.name, name, self.vals[name], value)) self.vals[name] = value
[docs] def get_name(self) -> str: """Return the name of the enum""" return self.name
[docs] def get_value(self, name: str) -> int: """Returns the value associated with a name :param name: Enumerator name :raises ValueError: If the given enumerator name is not part of the enumeration """ if name not in self.vals: raise ValueError('%s is not a valid name for enum %s' % (name, self.name)) return self.vals[name]
[docs] def has_value(self, name: str) -> bool: """Tells if the enum has value with the given name :param name: Enumerator name """ return name in self.vals
def get_def(self) -> EmbeddedEnumDef: """Exports to dict for json serialization mainly""" obj: EmbeddedEnumDef = { 'name': self.name, 'values': self.vals } return obj
[docs] def has_signed_value(self) -> bool: """Returns true if any value is negative""" for v in self.vals.values(): if v < 0: return True return False
def copy(self) -> "EmbeddedEnum": """Creates a copy of the enum""" return EmbeddedEnum(name=self.name, vals=self.vals) @classmethod def from_def(cls, enum_def: EmbeddedEnumDef) -> "EmbeddedEnum": """Recreates from a .json dict :param enum_def: The json structure created with :meth:`get_def<get_def>` """ obj = EmbeddedEnum(enum_def['name']) obj.vals = enum_def['values'] return obj