Skip to content

Snirk API Docs :: types

snirk.types

AddressEnum

Bases: Enum

Enum of address keys mapped to address and size.

Supports getting via attribute (per typical enum) as well as getting via string key.

Source code in snirk/types.py
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class AddressEnum(Enum):
    """Enum of address keys mapped to address and size.

    Supports getting via attribute (per typical enum) as well as getting via string key.
    """

    def __init__(self, address: int, size: int):
        self.address = address
        self.size = size

    @classmethod
    def get(cls, address: int):
        """Lookup by address."""
        return next(member for member in cls if member.address == address)

get classmethod

get(address)

Lookup by address.

Source code in snirk/types.py
22
23
24
25
@classmethod
def get(cls, address: int):
    """Lookup by address."""
    return next(member for member in cls if member.address == address)

MemData

Bases: UserDict

Dict-like container for mapping of memory addresses to values parsed from gRPC response.

Intended to be subclassed by apps using Snirk with a relevant AddressEnum subclass.

Allows lookup via indexing ("[...]") from: address enum (AddressEnum), memory address (int), or key (str). Preferred method is generally by AddressEnum for static use so mypy/type-checker can catch, instead of runtime errors (where possible).

Parameters:

Name Type Description Default
memclass Type[AddressEnum]

AddressEnum subclass associated with this MemData subclass

required
Source code in snirk/types.py
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
class MemData(UserDict):
    """Dict-like container for mapping of memory addresses to values parsed from gRPC response.

    Intended to be subclassed by apps using Snirk with a relevant AddressEnum subclass.

    Allows lookup via indexing ("[...]") from: address enum (AddressEnum), memory address (int), or key (str).
    Preferred method is generally by AddressEnum for static use so mypy/type-checker can catch, instead of
    runtime errors (where possible).

    :param memclass: AddressEnum subclass associated with this MemData subclass
    :type memclass: Type[AddressEnum]
    """

    # set in subclasses to a particular AddressEnum subclass
    memclass: ClassVar[Type[AddressEnum]]

    def __init__(self, response: Optional[Union[pb.MultiReadMemoryResponse, pb.SingleReadMemoryResponse]] = None):
        """Initialize memory data with optional parsing of gRPC response into data.

        :param response: SNI multi read memory response to parse
        """
        self.data: dict[AddressEnum, int] = {}

        if response:
            self.parse(response)

    def __getitem__(self, key: Union[AddressEnum, int, str]) -> int:
        """Lookup memory data via key.

        Try to lookup via key directly (e.g. AddressEnum). On KeyError, if int, perform lookup via address.
        When string, lookup via AddressEnum (using string). Otherwise, raise a KeyError.

        :param key: key to lookup from data
        :raises KeyError: cannot find key in data
        """
        if isinstance(key, int):
            return self.data[self.memclass.get(key)]
        elif isinstance(key, str):
            return self.data[self.memclass[key]]
        return self.data[key]

    @singledispatchmethod
    def parse(self, response):
        """Parse gRPC response into data.

        :param response: SNI single/multi read memory response to parse
        :type response: Union[pb.MultiReadMemoryResponse, pb.SingleReadMemoryResponse]
        """
        raise NotImplementedError(f"Cannot parse response: {response}")

    @parse.register
    def _(self, response: pb.MultiReadMemoryResponse):
        self.data = {self.memclass.get(msg.requestAddress): int(msg.data.hex(), 16) for msg in response.responses}

    @parse.register
    def _(self, response: pb.SingleReadMemoryResponse):
        msg = response.response
        self.data = {self.memclass.get(msg.requestAddress): int(msg.data.hex(), 16)}

__getitem__

__getitem__(key)

Lookup memory data via key.

Try to lookup via key directly (e.g. AddressEnum). On KeyError, if int, perform lookup via address. When string, lookup via AddressEnum (using string). Otherwise, raise a KeyError.

Parameters:

Name Type Description Default
key Union[AddressEnum, int, str]

key to lookup from data

required

Raises:

Type Description
KeyError

cannot find key in data

Source code in snirk/types.py
54
55
56
57
58
59
60
61
62
63
64
65
66
67
def __getitem__(self, key: Union[AddressEnum, int, str]) -> int:
    """Lookup memory data via key.

    Try to lookup via key directly (e.g. AddressEnum). On KeyError, if int, perform lookup via address.
    When string, lookup via AddressEnum (using string). Otherwise, raise a KeyError.

    :param key: key to lookup from data
    :raises KeyError: cannot find key in data
    """
    if isinstance(key, int):
        return self.data[self.memclass.get(key)]
    elif isinstance(key, str):
        return self.data[self.memclass[key]]
    return self.data[key]

__init__

__init__(response=None)

Initialize memory data with optional parsing of gRPC response into data.

Parameters:

Name Type Description Default
response Optional[Union[MultiReadMemoryResponse, SingleReadMemoryResponse]]

SNI multi read memory response to parse

None
Source code in snirk/types.py
44
45
46
47
48
49
50
51
52
def __init__(self, response: Optional[Union[pb.MultiReadMemoryResponse, pb.SingleReadMemoryResponse]] = None):
    """Initialize memory data with optional parsing of gRPC response into data.

    :param response: SNI multi read memory response to parse
    """
    self.data: dict[AddressEnum, int] = {}

    if response:
        self.parse(response)

parse

parse(response)

Parse gRPC response into data.

Parameters:

Name Type Description Default
response Union[pb.MultiReadMemoryResponse, pb.SingleReadMemoryResponse]

SNI single/multi read memory response to parse

required
Source code in snirk/types.py
69
70
71
72
73
74
75
76
@singledispatchmethod
def parse(self, response):
    """Parse gRPC response into data.

    :param response: SNI single/multi read memory response to parse
    :type response: Union[pb.MultiReadMemoryResponse, pb.SingleReadMemoryResponse]
    """
    raise NotImplementedError(f"Cannot parse response: {response}")