aboutsummaryrefslogtreecommitdiff
path: root/pyasn1
diff options
context:
space:
mode:
authorIlya Etingof <etingof@gmail.com>2017-09-13 01:10:42 +0200
committerIlya Etingof <etingof@gmail.com>2017-09-13 01:10:42 +0200
commitc40b8c22c9679e017871617d7cf558b1b7f0ff84 (patch)
treeea0c3a608294cb740c2a9e6b15f776143c8f2c27 /pyasn1
parent789a4e2f4f921fdac37f28df557319b89df3050c (diff)
downloadpyasn1-c40b8c22c9679e017871617d7cf558b1b7f0ff84.tar.gz
refactored OpenType() into a mutable object
Diffstat (limited to 'pyasn1')
-rw-r--r--pyasn1/codec/ber/decoder.py101
-rw-r--r--pyasn1/type/namedtype.py19
-rw-r--r--pyasn1/type/opentype.py24
3 files changed, 91 insertions, 53 deletions
diff --git a/pyasn1/codec/ber/decoder.py b/pyasn1/codec/ber/decoder.py
index 8aac8c9..4a1ef01 100644
--- a/pyasn1/codec/ber/decoder.py
+++ b/pyasn1/codec/ber/decoder.py
@@ -511,35 +511,45 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder):
seenIndices.add(idx)
idx += 1
- if namedTypes and options.get('decodeOpenTypes', False):
+ if namedTypes:
if not namedTypes.requiredComponents.issubset(seenIndices):
raise error.PyAsn1Error('ASN.1 object %s has uninitialized components' % asn1Object.__class__.__name__)
+ if namedTypes.hasOpenTypes:
- for idx, namedType in enumerate(namedTypes.namedTypes):
- if not namedType.openType:
- continue
+ openTypes = options.get('openTypes', {})
- governingValue = asn1Object.getComponentByName(
- namedType.openType.name
- )
+ if openTypes or options.get('decodeOpenTypes', False):
- try:
- asn1Spec = namedType.openType[governingValue]
+ for idx, namedType in enumerate(namedTypes.namedTypes):
+ if not namedType.openType:
+ continue
- except KeyError:
- continue
+ governingValue = asn1Object.getComponentByName(
+ namedType.openType.name
+ )
- component, rest = decodeFun(
- asn1Object.getComponentByPosition(idx).asOctets(),
- asn1Spec=asn1Spec
- )
+ try:
+ asn1Spec = openTypes[governingValue]
- asn1Object.setComponentByPosition(
- idx, component,
- matchTags=False,
- matchConstraints=False
- )
+ except KeyError:
+
+ try:
+ asn1Spec = namedType.openType[governingValue]
+
+ except KeyError:
+ continue
+
+ component, rest = decodeFun(
+ asn1Object.getComponentByPosition(idx).asOctets(),
+ asn1Spec=asn1Spec
+ )
+
+ asn1Object.setComponentByPosition(
+ idx, component,
+ matchTags=False,
+ matchConstraints=False
+ )
else:
asn1Object.verifySizeSpec()
@@ -637,31 +647,42 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder):
if not namedTypes.requiredComponents.issubset(seenIndices):
raise error.PyAsn1Error('ASN.1 object %s has uninitialized components' % asn1Object.__class__.__name__)
- for idx, namedType in enumerate(namedTypes.namedTypes):
- if not namedType.openType:
- continue
+ if namedTypes.hasOpenTypes:
- governingValue = asn1Object.getComponentByName(
- namedType.openType.name
- )
+ openTypes = options.get('openTypes', None)
- try:
- asn1Spec = namedType.openType[governingValue]
+ if openTypes or options.get('decodeOpenTypes', False):
- except KeyError:
- continue
+ for idx, namedType in enumerate(namedTypes.namedTypes):
+ if not namedType.openType:
+ continue
- component, rest = decodeFun(
- asn1Object.getComponentByPosition(idx).asOctets(),
- asn1Spec=asn1Spec, allowEoo=True
- )
+ governingValue = asn1Object.getComponentByName(
+ namedType.openType.name
+ )
- if component is not eoo.endOfOctets:
- asn1Object.setComponentByPosition(
- idx, component,
- matchTags=False,
- matchConstraints=False
- )
+ try:
+ asn1Spec = openTypes[governingValue]
+
+ except KeyError:
+
+ try:
+ asn1Spec = namedType.openType[governingValue]
+
+ except KeyError:
+ continue
+
+ component, rest = decodeFun(
+ asn1Object.getComponentByPosition(idx).asOctets(),
+ asn1Spec=asn1Spec, allowEoo=True
+ )
+
+ if component is not eoo.endOfOctets:
+ asn1Object.setComponentByPosition(
+ idx, component,
+ matchTags=False,
+ matchConstraints=False
+ )
else:
asn1Object.verifySizeSpec()
diff --git a/pyasn1/type/namedtype.py b/pyasn1/type/namedtype.py
index cba9524..edcf3ce 100644
--- a/pyasn1/type/namedtype.py
+++ b/pyasn1/type/namedtype.py
@@ -10,6 +10,12 @@ from pyasn1 import error
__all__ = ['NamedType', 'OptionalNamedType', 'DefaultedNamedType', 'NamedTypes']
+try:
+ any
+
+except AttributeError:
+ any = lambda x: bool(filter(bool, x))
+
class NamedType(object):
"""Create named field object for a constructed ASN.1 type.
@@ -120,8 +126,11 @@ class NamedTypes(object):
self.__ambiguousTypes = 'terminal' not in kwargs and self.__computeAmbiguousTypes() or {}
self.__uniqueTagMap = self.__computeTagMaps(unique=True)
self.__nonUniqueTagMap = self.__computeTagMaps(unique=False)
- self.__hasOptionalOrDefault = bool([True for namedType in self.__namedTypes
- if namedType.isDefaulted or namedType.isOptional])
+ self.__hasOptionalOrDefault = any([True for namedType in self.__namedTypes
+ if namedType.isDefaulted or namedType.isOptional])
+ self.__hasOpenTypes = any([True for namedType in self.__namedTypes
+ if namedType.openType])
+
self.__requiredComponents = frozenset(
[idx for idx, nt in enumerate(self.__namedTypes) if not nt.isOptional and not nt.isDefaulted]
)
@@ -508,8 +517,12 @@ class NamedTypes(object):
return self.__hasOptionalOrDefault
@property
+ def hasOpenTypes(self):
+ return self.__hasOpenTypes
+
+ @property
def namedTypes(self):
- return iter(self.__namedTypes)
+ return tuple(self.__namedTypes)
@property
def requiredComponents(self):
diff --git a/pyasn1/type/opentype.py b/pyasn1/type/opentype.py
index 9788a56..c8f0e64 100644
--- a/pyasn1/type/opentype.py
+++ b/pyasn1/type/opentype.py
@@ -21,13 +21,17 @@ class OpenType(object):
name: :py:class:`str`
Field name
- *choices:
- Sequence of (*value*, *type*) tuples representing the mapping
+ typeMap: :py:class:`dict`:
+ A map of value->ASN.1 type. It's stored by reference and can be
+ mutated later to register new mappings.
"""
- def __init__(self, name, args, **kwargs):
+ def __init__(self, name, typeMap=None):
self.__name = name
- self.__choices = dict(args, **kwargs)
+ if typeMap is None:
+ self.__typeMap = {}
+ else:
+ self.__typeMap = typeMap
@property
def name(self):
@@ -36,19 +40,19 @@ class OpenType(object):
# Python dict protocol
def values(self):
- return self.__choices.values()
+ return self.__typeMap.values()
def keys(self):
- return self.__choices
+ return self.__typeMap.keys()
def items(self):
- return self.__choices.items()
+ return self.__typeMap.items()
def __contains__(self, key):
- return key in self.__choices
+ return key in self.__typeMap
def __getitem__(self, key):
- return self.__choices[key]
+ return self.__typeMap[key]
def __iter__(self):
- return iter(self.__choices)
+ return iter(self.__typeMap)