summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIlya Etingof <etingof@gmail.com>2017-04-21 01:09:10 +0200
committerIlya Etingof <etingof@gmail.com>2017-04-21 01:09:10 +0200
commit6fb2b5ddc59ac08649bb5a68a2f82e59f165b04d (patch)
tree5f70e65a2d98f9e6a0f501ab65e310a1ad6f4910
parent2d92acee6fc8b581b39ba5bca5fd370c0fbe71af (diff)
downloadpyasn1-git-6fb2b5ddc59ac08649bb5a68a2f82e59f165b04d.tar.gz
ANY DEFINED BY decoding implemented
-rw-r--r--CHANGES.rst1
-rw-r--r--pyasn1/codec/ber/decoder.py13
-rw-r--r--pyasn1/type/namedtype.py28
3 files changed, 41 insertions, 1 deletions
diff --git a/CHANGES.rst b/CHANGES.rst
index 56f3fed..ce97e34 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -2,6 +2,7 @@
Revision 0.2.4, released XX-03-2017
-----------------------------------
+- ANY DEFINED BY clause support implemented
- ASN.1 types initialization refactored to minimize the use of
relatively expensive isNoValue() call
- Lazily pre-populate list of values of Sequence/Set/Choice types
diff --git a/pyasn1/codec/ber/decoder.py b/pyasn1/codec/ber/decoder.py
index e100e75..46f861d 100644
--- a/pyasn1/codec/ber/decoder.py
+++ b/pyasn1/codec/ber/decoder.py
@@ -403,6 +403,17 @@ class SequenceAndSetDecoderBase(AbstractConstructedDecoder):
matchTags=False, matchConstraints=False
)
+ for holeName, governingName, typesMap in namedTypes.holes:
+ holeComponent = asn1Object[holeName]
+ if holeComponent.isValue:
+ governingComponent = asn1Object[governingName]
+ if governingComponent in typesMap:
+ component, rest = decodeFun(
+ holeComponent.asOctets(),
+ asn1Spec=typesMap[governingComponent]
+ )
+ asn1Object.setComponentByName(holeName, component, matchTags=False, matchConstraints=False)
+
if not namedTypes:
asn1Object.verifySizeSpec()
@@ -1008,7 +1019,7 @@ class Decoder(object):
'codec %s yields type %s, value:\n%s\n...remaining substrate is: %s' % (concreteDecoder.__class__.__name__, value.__class__.__name__, value.prettyPrint(), substrate and debug.hexdump(substrate) or '<none>'))
if state == stErrorCondition:
raise error.PyAsn1Error(
- '%s not in asn1Spec: %s' % (tagSet, asn1Spec)
+ '%s not in asn1Spec: %r' % (tagSet, asn1Spec)
)
if debug.logger and debug.logger & debug.flagDecoder:
debug.scope.pop()
diff --git a/pyasn1/type/namedtype.py b/pyasn1/type/namedtype.py
index 3f9ae19..710ce93 100644
--- a/pyasn1/type/namedtype.py
+++ b/pyasn1/type/namedtype.py
@@ -34,6 +34,8 @@ class NamedType(object):
self.__name = name
self.__type = asn1Object
self.__nameAndType = name, asn1Object
+ self.__governingName = None
+ self.__typesMap = None
def __repr__(self):
return '%s(%r, %r)' % (self.__class__.__name__, self.__name, self.__type)
@@ -73,6 +75,19 @@ class NamedType(object):
def asn1Object(self):
return self.__type
+ def definedBy(self, governingName, typesMap):
+ self.__governingName = governingName
+ self.__typesMap = typesMap
+ return self
+
+ @property
+ def governingName(self):
+ return self.__governingName
+
+ @property
+ def typesMap(self):
+ return self.__typesMap
+
# Backward compatibility
def getName(self):
@@ -116,6 +131,7 @@ class NamedTypes(object):
self.__tagMap = {}
self.__hasOptionalOrDefault = None
self.__requiredComponents = None
+ self.__holes = None
def __repr__(self):
return '%s(%s)' % (
@@ -473,3 +489,15 @@ class NamedTypes(object):
[idx for idx, nt in enumerate(self.__namedTypes) if not nt.isOptional and not nt.isDefaulted]
)
return self.__requiredComponents
+
+ @property
+ def holes(self):
+ if self.__holes is None:
+ holes = []
+ for namedType in self.__namedTypes:
+ if namedType.governingName:
+ holes.append((namedType.name, namedType.governingName, namedType.typesMap))
+
+ self.__holes = holes
+
+ return self.__holes