diff options
author | Ilya Etingof <etingof@gmail.com> | 2017-09-13 01:10:42 +0200 |
---|---|---|
committer | Ilya Etingof <etingof@gmail.com> | 2017-09-13 01:10:42 +0200 |
commit | c40b8c22c9679e017871617d7cf558b1b7f0ff84 (patch) | |
tree | ea0c3a608294cb740c2a9e6b15f776143c8f2c27 /pyasn1 | |
parent | 789a4e2f4f921fdac37f28df557319b89df3050c (diff) | |
download | pyasn1-c40b8c22c9679e017871617d7cf558b1b7f0ff84.tar.gz |
refactored OpenType() into a mutable object
Diffstat (limited to 'pyasn1')
-rw-r--r-- | pyasn1/codec/ber/decoder.py | 101 | ||||
-rw-r--r-- | pyasn1/type/namedtype.py | 19 | ||||
-rw-r--r-- | pyasn1/type/opentype.py | 24 |
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) |