1#
2# This file is part of pyasn1 software.
3#
4# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com>
5# License: http://snmplabs.com/pyasn1/license.html
6#
7from pyasn1 import error
8
9__all__ = ['TagMap']
10
11
12class TagMap(object):
13    """Map *TagSet* objects to ASN.1 types
14
15    Create an object mapping *TagSet* object to ASN.1 type.
16
17    *TagMap* objects are immutable and duck-type read-only Python
18    :class:`dict` objects holding *TagSet* objects as keys and ASN.1
19    type objects as values.
20
21    Parameters
22    ----------
23    presentTypes: :py:class:`dict`
24        Map of :class:`~pyasn1.type.tag.TagSet` to ASN.1 objects considered
25        as being unconditionally present in the *TagMap*.
26
27    skipTypes: :py:class:`dict`
28        A collection of :class:`~pyasn1.type.tag.TagSet` objects considered
29        as absent in the *TagMap* even when *defaultType* is present.
30
31    defaultType: ASN.1 type object
32        An ASN.1 type object callee *TagMap* returns for any *TagSet* key not present
33        in *presentTypes* (unless given key is present in *skipTypes*).
34    """
35    def __init__(self, presentTypes=None, skipTypes=None, defaultType=None):
36        self.__presentTypes = presentTypes or {}
37        self.__skipTypes = skipTypes or {}
38        self.__defaultType = defaultType
39
40    def __contains__(self, tagSet):
41        return (tagSet in self.__presentTypes or
42                self.__defaultType is not None and tagSet not in self.__skipTypes)
43
44    def __getitem__(self, tagSet):
45        try:
46            return self.__presentTypes[tagSet]
47        except KeyError:
48            if self.__defaultType is None:
49                raise KeyError()
50            elif tagSet in self.__skipTypes:
51                raise error.PyAsn1Error('Key in negative map')
52            else:
53                return self.__defaultType
54
55    def __iter__(self):
56        return iter(self.__presentTypes)
57
58    def __repr__(self):
59        representation = '%s object' % self.__class__.__name__
60
61        if self.__presentTypes:
62            representation += ', present %s' % repr(self.__presentTypes)
63
64        if self.__skipTypes:
65            representation += ', skip %s' % repr(self.__skipTypes)
66
67        if self.__defaultType is not None:
68            representation += ', default %s' % repr(self.__defaultType)
69
70        return '<%s>' % representation
71
72    @property
73    def presentTypes(self):
74        """Return *TagSet* to ASN.1 type map present in callee *TagMap*"""
75        return self.__presentTypes
76
77    @property
78    def skipTypes(self):
79        """Return *TagSet* collection unconditionally absent in callee *TagMap*"""
80        return self.__skipTypes
81
82    @property
83    def defaultType(self):
84        """Return default ASN.1 type being returned for any missing *TagSet*"""
85        return self.__defaultType
86
87    # Backward compatibility
88
89    def getPosMap(self):
90        return self.presentTypes
91
92    def getNegMap(self):
93        return self.skipTypes
94
95    def getDef(self):
96        return self.defaultType
97