summaryrefslogtreecommitdiffstats
path: root/sploit/types/indextbl.py
blob: 4f57a59c3ce08044197a2fa0d58fb72d97e049fe (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
from abc import abstractmethod
from collections.abc import Collection

from sploit.types.index_entry import IndexEntry

class IndexTbl(IndexEntry, Collection):
    """
    Abstract Index Table

    IndexTbl is a common interface to an abstracted key-value store.  The
    storage mechanism as well as lookup semantics are defined by concrete
    implementations.  "Index" in this case is more akin to a directory index or
    book index than a strictly numeric array index.

    In general, concrete tables may store values of any or multiple different
    types.  In particular, tables should give special accommodation for values
    of type IndexEntry.  These objects usually represent "rich" versions of the
    nominal data types the table expects to contain.  Implementation repr()
    methods usually also annotate which members are IndexEntries.

    IndexTbl extends from IndexEntry, and so has a base value which represents
    the "base index" of the table.  The meaning of this depends on the
    implementation.  This inheritance also means that tables are generally
    expected to be nestable.

    IndexTbls allow indices to be accessed via attribute or subscript notation.
    This is probably the key characteristic feature of the class.  The class
    namespace is kept as clean as possible to make for the fewest collisions
    between index names and other (real) class attributes.  Note that there are
    abstract methods, required to be overridden, which implement the index
    access.  These methods are only called for normal indices, not the table
    base.

    Because this class overrides attribute access, normal automatic object
    copying is broken.  Because of this, implementations must also provide a
    definition for the __copy__() method as well.
    """

    @abstractmethod
    def __getindex__(self, index):
        """Lookup and retrieve index value."""
        raise NotImplementedError

    @abstractmethod
    def __setindex__(self, index, value):
        """Lookup and set index value."""
        raise NotImplementedError

    @abstractmethod
    def __delindex__(self, index):
        """Lookup and delete index value."""
        raise NotImplementedError

    @abstractmethod
    def __copy__(self):
        """Create a copy of this IndexTbl object."""
        raise NotImplementedError

    def __contains__(self, index):
        """Test the existence of the given index."""
        try:
            self.__getindex__(index)
        except KeyError:
            return False
        else:
            return True

    # Attribute access methods

    def __getattr__(self, index):
        """Get value via attribute."""
        return self[index]

    def __setattr__(self, index, value):
        """Set value via attribute."""
        self[index] = value

    def __delattr__(self, index):
        """Delete value via attribute."""
        del self[index]

    # Subscript/item access methods

    def __getitem__(self, index):
        """Get value via subscript."""
        if index == "base":
            return self.base
        return self.__getindex__(index)

    def __setitem__(self, index, value):
        """Set value via subscript."""
        if index == "base":
            object.__setattr__(self, "base", value)
        elif index in dir(self):
            raise KeyError(f"IndexTbl: Index is reserved: {index}")
        else:
            self.__setindex__(index, value)

    def __delitem__(self, index):
        """Delete value via subscript."""
        if index == "base":
            raise KeyError("IndexTbl: May not delete index: base")
        self.__delindex__(index)