1# Base classes for ASN.1 types
2import sys
3from pyasn1.type import constraint, tagmap
4from pyasn1 import error
5
6class Asn1Item: pass
7
8class Asn1ItemBase(Asn1Item):
9    # Set of tags for this ASN.1 type
10    tagSet = ()
11
12    # A list of constraint.Constraint instances for checking values
13    subtypeSpec = constraint.ConstraintsIntersection()
14
15    # Used for ambiguous ASN.1 types identification
16    typeId = None
17
18    def __init__(self, tagSet=None, subtypeSpec=None):
19        if tagSet is None:
20            self._tagSet = self.tagSet
21        else:
22            self._tagSet = tagSet
23        if subtypeSpec is None:
24            self._subtypeSpec = self.subtypeSpec
25        else:
26            self._subtypeSpec = subtypeSpec
27
28    def _verifySubtypeSpec(self, value, idx=None):
29        try:
30            self._subtypeSpec(value, idx)
31        except error.PyAsn1Error:
32            c, i, t = sys.exc_info()
33            raise c('%s at %s' % (i, self.__class__.__name__))
34
35    def getSubtypeSpec(self): return self._subtypeSpec
36
37    def getTagSet(self): return self._tagSet
38    def getEffectiveTagSet(self): return self._tagSet  # used by untagged types
39    def getTagMap(self): return tagmap.TagMap({self._tagSet: self})
40
41    def isSameTypeWith(self, other):
42        return self is other or \
43               self._tagSet == other.getTagSet() and \
44               self._subtypeSpec == other.getSubtypeSpec()
45    def isSuperTypeOf(self, other):
46        """Returns true if argument is a ASN1 subtype of ourselves"""
47        return self._tagSet.isSuperTagSetOf(other.getTagSet()) and \
48               self._subtypeSpec.isSuperTypeOf(other.getSubtypeSpec())
49
50class __NoValue:
51    def __getattr__(self, attr):
52        raise error.PyAsn1Error('No value for %s()' % attr)
53    def __getitem__(self, i):
54        raise error.PyAsn1Error('No value')
55
56noValue = __NoValue()
57
58# Base class for "simple" ASN.1 objects. These are immutable.
59class AbstractSimpleAsn1Item(Asn1ItemBase):
60    defaultValue = noValue
61    def __init__(self, value=None, tagSet=None, subtypeSpec=None):
62        Asn1ItemBase.__init__(self, tagSet, subtypeSpec)
63        if value is None or value is noValue:
64            value = self.defaultValue
65        if value is None or value is noValue:
66            self.__hashedValue = value = noValue
67        else:
68            value = self.prettyIn(value)
69            self._verifySubtypeSpec(value)
70            self.__hashedValue = hash(value)
71        self._value = value
72        self._len = None
73
74    def __repr__(self):
75        if self._value is noValue:
76            return self.__class__.__name__ + '()'
77        else:
78            return self.__class__.__name__ + '(%s)' % (self.prettyOut(self._value),)
79    def __str__(self): return str(self._value)
80    def __eq__(self, other):
81        return self is other and True or self._value == other
82    def __ne__(self, other): return self._value != other
83    def __lt__(self, other): return self._value < other
84    def __le__(self, other): return self._value <= other
85    def __gt__(self, other): return self._value > other
86    def __ge__(self, other): return self._value >= other
87    if sys.version_info[0] <= 2:
88        def __nonzero__(self): return bool(self._value)
89    else:
90        def __bool__(self): return bool(self._value)
91    def __hash__(self): return self.__hashedValue
92
93    def clone(self, value=None, tagSet=None, subtypeSpec=None):
94        if value is None and tagSet is None and subtypeSpec is None:
95            return self
96        if value is None:
97            value = self._value
98        if tagSet is None:
99            tagSet = self._tagSet
100        if subtypeSpec is None:
101            subtypeSpec = self._subtypeSpec
102        return self.__class__(value, tagSet, subtypeSpec)
103
104    def subtype(self, value=None, implicitTag=None, explicitTag=None,
105                subtypeSpec=None):
106        if value is None:
107            value = self._value
108        if implicitTag is not None:
109            tagSet = self._tagSet.tagImplicitly(implicitTag)
110        elif explicitTag is not None:
111            tagSet = self._tagSet.tagExplicitly(explicitTag)
112        else:
113            tagSet = self._tagSet
114        if subtypeSpec is None:
115            subtypeSpec = self._subtypeSpec
116        else:
117            subtypeSpec = subtypeSpec + self._subtypeSpec
118        return self.__class__(value, tagSet, subtypeSpec)
119
120    def prettyIn(self, value): return value
121    def prettyOut(self, value): return str(value)
122
123    def prettyPrint(self, scope=0):
124        if self._value is noValue:
125            return '<no value>'
126        else:
127            return self.prettyOut(self._value)
128
129    # XXX Compatibility stub
130    def prettyPrinter(self, scope=0): return self.prettyPrint(scope)
131
132#
133# Constructed types:
134# * There are five of them: Sequence, SequenceOf/SetOf, Set and Choice
135# * ASN1 types and values are represened by Python class instances
136# * Value initialization is made for defaulted components only
137# * Primary method of component addressing is by-position. Data model for base
138#   type is Python sequence. Additional type-specific addressing methods
139#   may be implemented for particular types.
140# * SequenceOf and SetOf types do not implement any additional methods
141# * Sequence, Set and Choice types also implement by-identifier addressing
142# * Sequence, Set and Choice types also implement by-asn1-type (tag) addressing
143# * Sequence and Set types may include optional and defaulted
144#   components
145# * Constructed types hold a reference to component types used for value
146#   verification and ordering.
147# * Component type is a scalar type for SequenceOf/SetOf types and a list
148#   of types for Sequence/Set/Choice.
149#
150
151class AbstractConstructedAsn1Item(Asn1ItemBase):
152    componentType = None
153    sizeSpec = constraint.ConstraintsIntersection()
154    def __init__(self, componentType=None, tagSet=None,
155                 subtypeSpec=None, sizeSpec=None):
156        Asn1ItemBase.__init__(self, tagSet, subtypeSpec)
157        if componentType is None:
158            self._componentType = self.componentType
159        else:
160            self._componentType = componentType
161        if sizeSpec is None:
162            self._sizeSpec = self.sizeSpec
163        else:
164            self._sizeSpec = sizeSpec
165        self._componentValues = []
166        self._componentValuesSet = 0
167
168    def __repr__(self):
169        r = self.__class__.__name__ + '()'
170        for idx in range(len(self._componentValues)):
171            if self._componentValues[idx] is None:
172                continue
173            r = r + '.setComponentByPosition(%s, %r)' % (
174                idx, self._componentValues[idx]
175                )
176        return r
177
178    def __eq__(self, other):
179        return self is other and True or self._componentValues == other
180    def __ne__(self, other): return self._componentValues != other
181    def __lt__(self, other): return self._componentValues < other
182    def __le__(self, other): return self._componentValues <= other
183    def __gt__(self, other): return self._componentValues > other
184    def __ge__(self, other): return self._componentValues >= other
185    if sys.version_info[0] <= 2:
186        def __nonzero__(self): return bool(self._componentValues)
187    else:
188        def __bool__(self): return bool(self._componentValues)
189
190    def getComponentTagMap(self):
191        raise error.PyAsn1Error('Method not implemented')
192
193    def _cloneComponentValues(self, myClone, cloneValueFlag): pass
194
195    def clone(self, tagSet=None, subtypeSpec=None, sizeSpec=None,
196              cloneValueFlag=None):
197        if tagSet is None:
198            tagSet = self._tagSet
199        if subtypeSpec is None:
200            subtypeSpec = self._subtypeSpec
201        if sizeSpec is None:
202            sizeSpec = self._sizeSpec
203        r = self.__class__(self._componentType, tagSet, subtypeSpec, sizeSpec)
204        if cloneValueFlag:
205            self._cloneComponentValues(r, cloneValueFlag)
206        return r
207
208    def subtype(self, implicitTag=None, explicitTag=None, subtypeSpec=None,
209                sizeSpec=None, cloneValueFlag=None):
210        if implicitTag is not None:
211            tagSet = self._tagSet.tagImplicitly(implicitTag)
212        elif explicitTag is not None:
213            tagSet = self._tagSet.tagExplicitly(explicitTag)
214        else:
215            tagSet = self._tagSet
216        if subtypeSpec is None:
217            subtypeSpec = self._subtypeSpec
218        else:
219            subtypeSpec = subtypeSpec + self._subtypeSpec
220        if sizeSpec is None:
221            sizeSpec = self._sizeSpec
222        else:
223            sizeSpec = sizeSpec + self._sizeSpec
224        r = self.__class__(self._componentType, tagSet, subtypeSpec, sizeSpec)
225        if cloneValueFlag:
226            self._cloneComponentValues(r, cloneValueFlag)
227        return r
228
229    def _verifyComponent(self, idx, value): pass
230
231    def verifySizeSpec(self): self._sizeSpec(self)
232
233    def getComponentByPosition(self, idx):
234        raise error.PyAsn1Error('Method not implemented')
235    def setComponentByPosition(self, idx, value, verifyConstraints=True):
236        raise error.PyAsn1Error('Method not implemented')
237
238    def getComponentType(self): return self._componentType
239
240    def __getitem__(self, idx): return self.getComponentByPosition(idx)
241    def __setitem__(self, idx, value): self.setComponentByPosition(idx, value)
242
243    def __len__(self): return len(self._componentValues)
244
245    def clear(self):
246        self._componentValues = []
247        self._componentValuesSet = 0
248
249    def setDefaultComponents(self): pass
250