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