>>> i = Integer(123)
>>> raw = i.encode()
- >>> Integer().decode(raw) == i
+ >>> Integer().decod(raw) == i
True
There are primitive types, holding single values
Most types in ASN.1 has specific tag for them. ``Obj.tag_default`` is
the default tag used during coding process. You can override it with
-either ``IMPLICIT`` (using ``impl`` keyword argument), or
-``EXPLICIT`` one (using ``expl`` keyword argument). Both arguments take
-raw binary string, containing that tag. You can **not** set implicit and
-explicit tags simultaneously.
+either ``IMPLICIT`` (using either ``impl`` keyword argument or ``impl``
+class attribute), or ``EXPLICIT`` one (using either ``expl`` keyword
+argument or ``expl`` class attribute). Both arguments take raw binary
+string, containing that tag. You can **not** set implicit and explicit
+tags simultaneously.
There are :py:func:`pyderasn.tag_ctxp` and :py:func:`pyderasn.tag_ctxc`
functions, allowing you to easily create ``CONTEXT``
ready to be encoded. If that kind of action is performed on unready
object, then :py:exc:`pyderasn.ObjNotReady` exception will be raised.
-All objects have ``copy()`` method, that returns their copy, that can be
+All objects are friendly to ``copy.copy()`` and copied objects can be
safely mutated.
+Also all objects can be safely ``pickle``-d, but pay attention that
+pickling among different PyDERASN versions is prohibited.
+
.. _decoding:
Decoding
--------
-Decoding is performed using ``decode()`` method. ``offset`` optional
-argument could be used to set initial object's offset in the binary
-data, for convenience. It returns decoded object and remaining
-unmarshalled data (tail). Internally all work is done on
+Decoding is performed using :py:meth:`pyderasn.Obj.decode` method.
+``offset`` optional argument could be used to set initial object's
+offset in the binary data, for convenience. It returns decoded object
+and remaining unmarshalled data (tail). Internally all work is done on
``memoryview(data)``, and you can leave returning tail as a memoryview,
by specifying ``leavemm=True`` argument.
+Also note convenient :py:meth:`pyderasn.Obj.decod` method, that
+immediately checks and raises if there is non-empty tail.
+
When object is decoded, ``decoded`` property is true and you can safely
use following properties:
Context
_______
-You can specify so called context keyword argument during ``decode()``
-invocation. It is dictionary containing various options governing
-decoding process.
+You can specify so called context keyword argument during
+:py:meth:`pyderasn.Obj.decode` invocation. It is dictionary containing
+various options governing decoding process.
Currently available context options:
structures it may hold. Also, automatically decode ``controlSequence``
of ``PKIResponse``::
- content_info, tail = ContentInfo().decode(data, ctx={"defines_by_path": (
+ content_info = ContentInfo().decod(data, ctx={"defines_by_path": (
(
("contentType",),
((("content",), {id_signedData: SignedData()}),),
PrintableString
_______________
.. autoclass:: pyderasn.PrintableString
+ :members: __init__
UTCTime
_______
.. autoclass:: pyderasn.DecodeError
:members: __init__
.. autoclass:: pyderasn.NotEnoughData
+.. autoclass:: pyderasn.ExceedingData
.. autoclass:: pyderasn.LenIndefForm
.. autoclass:: pyderasn.TagMismatch
.. autoclass:: pyderasn.InvalidLength
from os import environ
from string import ascii_letters
from string import digits
+from unicodedata import category as unicat
from six import add_metaclass
from six import binary_type
def colored(what, *args, **kwargs):
return what
-__version__ = "5.5"
+__version__ = "6.0"
__all__ = (
"Any",
"DecodeError",
"DecodePathDefBy",
"Enumerated",
+ "ExceedingData",
"GeneralizedTime",
"GeneralString",
"GraphicString",
pass
+class ExceedingData(ASN1Error):
+ def __init__(self, nbytes):
+ super(ExceedingData, self).__init__()
+ self.nbytes = nbytes
+
+ def __str__(self):
+ return "%d trailing bytes" % self.nbytes
+
+ def __repr__(self):
+ return "%s(%s)" % (self.__class__.__name__, self)
+
+
class LenIndefForm(DecodeError):
pass
"""
return (self.llen + self.vlen) > 0
- def copy(self): # pragma: no cover
- """Make a copy of object, safe to be mutated
+ def __getstate__(self): # pragma: no cover
+ """Used for making safe to be mutable pickleable copies
"""
raise NotImplementedError()
+ def __setstate__(self, state):
+ if state.version != __version__:
+ raise ValueError("data is pickled by different PyDERASN version")
+ self.tag = self.tag_default
+ self._value = None
+ self._expl = None
+ self.default = None
+ self.optional = False
+ self.offset = 0
+ self.llen = 0
+ self.vlen = 0
+ self.expl_lenindef = False
+ self.lenindef = False
+ self.ber_encoded = False
+
@property
def tlen(self):
"""See :ref:`decoding`
:param tag_only: decode only the tag, without length and contents
(used only in Choice and Set structures, trying to
determine if tag satisfies the scheme)
- :param _ctx_immutable: do we need to copy ``ctx`` before using it
+ :param _ctx_immutable: do we need to ``copy.copy()`` ``ctx``
+ before using it?
:returns: (Obj, remaining data)
.. seealso:: :ref:`decoding`
)
return obj, (tail if leavemm else tail.tobytes())
+ def decod(self, data, offset=0, decode_path=(), ctx=None):
+ """Decode the data, check that tail is empty
+
+ :raises ExceedingData: if tail is not empty
+
+ This is just a wrapper over :py:meth:`pyderasn.Obj.decode`
+ (decode without tail) that also checks that there is no
+ trailing data left.
+ """
+ obj, tail = self.decode(
+ data,
+ offset=offset,
+ decode_path=decode_path,
+ ctx=ctx,
+ leavemm=True,
+ )
+ if len(tail) > 0:
+ raise ExceedingData(len(tail))
+ return obj
+
@property
def expled(self):
"""See :ref:`decoding`
def pps_lenindef(self, decode_path):
if self.lenindef and not (
- getattr(self, "defined", None) is not None and
- self.defined[1].lenindef
+ getattr(self, "defined", None) is not None and
+ self.defined[1].lenindef
):
yield _pp(
asn1_type_name="EOC",
for pp in pps:
if hasattr(pp, "_fields"):
if (
- decode_path_only != () and
- tuple(
- str(p) for p in pp.decode_path[:len(decode_path_only)]
- ) != decode_path_only
+ decode_path_only != () and
+ tuple(
+ str(p) for p in pp.decode_path[:len(decode_path_only)]
+ ) != decode_path_only
):
continue
if big_blobs:
decode_path_len_decrease=len(decode_path_only),
)
for row in pp_console_blob(
- pp,
- decode_path_len_decrease=len(decode_path_only),
+ pp,
+ decode_path_len_decrease=len(decode_path_only),
):
yield row
else:
# ASN.1 primitive types
########################################################################
+BooleanState = namedtuple("BooleanState", (
+ "version",
+ "value",
+ "tag",
+ "expl",
+ "default",
+ "optional",
+ "offset",
+ "llen",
+ "vlen",
+ "expl_lenindef",
+ "lenindef",
+ "ber_encoded",
+))
+
+
class Boolean(Obj):
"""``BOOLEAN`` boolean type
def ready(self):
return self._value is not None
- def copy(self):
- obj = self.__class__()
- obj._value = self._value
- obj.tag = self.tag
- obj._expl = self._expl
- obj.default = self.default
- obj.optional = self.optional
- obj.offset = self.offset
- obj.llen = self.llen
- obj.vlen = self.vlen
- obj.expl_lenindef = self.expl_lenindef
- obj.lenindef = self.lenindef
- obj.ber_encoded = self.ber_encoded
- return obj
+ def __getstate__(self):
+ return BooleanState(
+ __version__,
+ self._value,
+ self.tag,
+ self._expl,
+ self.default,
+ self.optional,
+ self.offset,
+ self.llen,
+ self.vlen,
+ self.expl_lenindef,
+ self.lenindef,
+ self.ber_encoded,
+ )
+
+ def __setstate__(self, state):
+ super(Boolean, self).__setstate__(state)
+ self._value = state.value
+ self.tag = state.tag
+ self._expl = state.expl
+ self.default = state.default
+ self.optional = state.optional
+ self.offset = state.offset
+ self.llen = state.llen
+ self.vlen = state.vlen
+ self.expl_lenindef = state.expl_lenindef
+ self.lenindef = state.lenindef
+ self.ber_encoded = state.ber_encoded
def __nonzero__(self):
self._assert_ready()
yield pp
+IntegerState = namedtuple("IntegerState", (
+ "version",
+ "specs",
+ "value",
+ "bound_min",
+ "bound_max",
+ "tag",
+ "expl",
+ "default",
+ "optional",
+ "offset",
+ "llen",
+ "vlen",
+ "expl_lenindef",
+ "lenindef",
+ "ber_encoded",
+))
+
+
class Integer(Obj):
"""``INTEGER`` integer type
def ready(self):
return self._value is not None
- def copy(self):
- obj = self.__class__(_specs=self.specs)
- obj._value = self._value
- obj._bound_min = self._bound_min
- obj._bound_max = self._bound_max
- obj.tag = self.tag
- obj._expl = self._expl
- obj.default = self.default
- obj.optional = self.optional
- obj.offset = self.offset
- obj.llen = self.llen
- obj.vlen = self.vlen
- obj.expl_lenindef = self.expl_lenindef
- obj.lenindef = self.lenindef
- obj.ber_encoded = self.ber_encoded
- return obj
+ def __getstate__(self):
+ return IntegerState(
+ __version__,
+ self.specs,
+ self._value,
+ self._bound_min,
+ self._bound_max,
+ self.tag,
+ self._expl,
+ self.default,
+ self.optional,
+ self.offset,
+ self.llen,
+ self.vlen,
+ self.expl_lenindef,
+ self.lenindef,
+ self.ber_encoded,
+ )
+
+ def __setstate__(self, state):
+ super(Integer, self).__setstate__(state)
+ self.specs = state.specs
+ self._value = state.value
+ self._bound_min = state.bound_min
+ self._bound_max = state.bound_max
+ self.tag = state.tag
+ self._expl = state.expl
+ self.default = state.default
+ self.optional = state.optional
+ self.offset = state.offset
+ self.llen = state.llen
+ self.vlen = state.vlen
+ self.expl_lenindef = state.expl_lenindef
+ self.lenindef = state.lenindef
+ self.ber_encoded = state.ber_encoded
def __int__(self):
self._assert_ready()
SET01 = frozenset(("0", "1"))
+BitStringState = namedtuple("BitStringState", (
+ "version",
+ "specs",
+ "value",
+ "tag",
+ "expl",
+ "default",
+ "optional",
+ "offset",
+ "llen",
+ "vlen",
+ "expl_lenindef",
+ "lenindef",
+ "ber_encoded",
+ "tag_constructed",
+ "defined",
+))
class BitString(Obj):
def ready(self):
return self._value is not None
- def copy(self):
- obj = self.__class__(_specs=self.specs)
- value = self._value
- if value is not None:
- value = (value[0], value[1])
- obj._value = value
- obj.tag = self.tag
- obj._expl = self._expl
- obj.default = self.default
- obj.optional = self.optional
- obj.offset = self.offset
- obj.llen = self.llen
- obj.vlen = self.vlen
- obj.expl_lenindef = self.expl_lenindef
- obj.lenindef = self.lenindef
- obj.ber_encoded = self.ber_encoded
- return obj
+ def __getstate__(self):
+ return BitStringState(
+ __version__,
+ self.specs,
+ self._value,
+ self.tag,
+ self._expl,
+ self.default,
+ self.optional,
+ self.offset,
+ self.llen,
+ self.vlen,
+ self.expl_lenindef,
+ self.lenindef,
+ self.ber_encoded,
+ self.tag_constructed,
+ self.defined,
+ )
+
+ def __setstate__(self, state):
+ super(BitString, self).__setstate__(state)
+ self.specs = state.specs
+ self._value = state.value
+ self.tag = state.tag
+ self._expl = state.expl
+ self.default = state.default
+ self.optional = state.optional
+ self.offset = state.offset
+ self.llen = state.llen
+ self.vlen = state.vlen
+ self.expl_lenindef = state.expl_lenindef
+ self.lenindef = state.lenindef
+ self.ber_encoded = state.ber_encoded
+ self.tag_constructed = state.tag_constructed
+ self.defined = state.defined
def __iter__(self):
self._assert_ready()
yield pp
+OctetStringState = namedtuple("OctetStringState", (
+ "version",
+ "value",
+ "bound_min",
+ "bound_max",
+ "tag",
+ "expl",
+ "default",
+ "optional",
+ "offset",
+ "llen",
+ "vlen",
+ "expl_lenindef",
+ "lenindef",
+ "ber_encoded",
+ "tag_constructed",
+ "defined",
+))
+
+
class OctetString(Obj):
"""``OCTET STRING`` binary string type
:param default: set default value. Type same as in ``value``
:param bool optional: is object ``OPTIONAL`` in sequence
"""
- super(OctetString, self).__init__(
- impl,
- expl,
- default,
- optional,
- _decoded,
- )
+ super(OctetString, self).__init__(impl, expl, default, optional, _decoded)
self._value = value
self._bound_min, self._bound_max = getattr(
self,
def ready(self):
return self._value is not None
- def copy(self):
- obj = self.__class__()
- obj._value = self._value
- obj._bound_min = self._bound_min
- obj._bound_max = self._bound_max
- obj.tag = self.tag
- obj._expl = self._expl
- obj.default = self.default
- obj.optional = self.optional
- obj.offset = self.offset
- obj.llen = self.llen
- obj.vlen = self.vlen
- obj.expl_lenindef = self.expl_lenindef
- obj.lenindef = self.lenindef
- obj.ber_encoded = self.ber_encoded
- return obj
+ def __getstate__(self):
+ return OctetStringState(
+ __version__,
+ self._value,
+ self._bound_min,
+ self._bound_max,
+ self.tag,
+ self._expl,
+ self.default,
+ self.optional,
+ self.offset,
+ self.llen,
+ self.vlen,
+ self.expl_lenindef,
+ self.lenindef,
+ self.ber_encoded,
+ self.tag_constructed,
+ self.defined,
+ )
+
+ def __setstate__(self, state):
+ super(OctetString, self).__setstate__(state)
+ self._value = state.value
+ self._bound_min = state.bound_min
+ self._bound_max = state.bound_max
+ self.tag = state.tag
+ self._expl = state.expl
+ self.default = state.default
+ self.optional = state.optional
+ self.offset = state.offset
+ self.llen = state.llen
+ self.vlen = state.vlen
+ self.expl_lenindef = state.expl_lenindef
+ self.lenindef = state.lenindef
+ self.ber_encoded = state.ber_encoded
+ self.tag_constructed = state.tag_constructed
+ self.defined = state.defined
def __bytes__(self):
self._assert_ready()
yield pp
+NullState = namedtuple("NullState", (
+ "version",
+ "tag",
+ "expl",
+ "default",
+ "optional",
+ "offset",
+ "llen",
+ "vlen",
+ "expl_lenindef",
+ "lenindef",
+ "ber_encoded",
+))
+
+
class Null(Obj):
"""``NULL`` null object
def ready(self):
return True
- def copy(self):
- obj = self.__class__()
- obj.tag = self.tag
- obj._expl = self._expl
- obj.default = self.default
- obj.optional = self.optional
- obj.offset = self.offset
- obj.llen = self.llen
- obj.vlen = self.vlen
- obj.expl_lenindef = self.expl_lenindef
- obj.lenindef = self.lenindef
- obj.ber_encoded = self.ber_encoded
- return obj
+ def __getstate__(self):
+ return NullState(
+ __version__,
+ self.tag,
+ self._expl,
+ self.default,
+ self.optional,
+ self.offset,
+ self.llen,
+ self.vlen,
+ self.expl_lenindef,
+ self.lenindef,
+ self.ber_encoded,
+ )
+
+ def __setstate__(self, state):
+ super(Null, self).__setstate__(state)
+ self.tag = state.tag
+ self._expl = state.expl
+ self.default = state.default
+ self.optional = state.optional
+ self.offset = state.offset
+ self.llen = state.llen
+ self.vlen = state.vlen
+ self.expl_lenindef = state.expl_lenindef
+ self.lenindef = state.lenindef
+ self.ber_encoded = state.ber_encoded
def __eq__(self, their):
if not issubclass(their.__class__, Null):
yield pp
+ObjectIdentifierState = namedtuple("ObjectIdentifierState", (
+ "version",
+ "value",
+ "tag",
+ "expl",
+ "default",
+ "optional",
+ "offset",
+ "llen",
+ "vlen",
+ "expl_lenindef",
+ "lenindef",
+ "ber_encoded",
+ "defines",
+))
+
+
class ObjectIdentifier(Obj):
"""``OBJECT IDENTIFIER`` OID type
:param default: set default value. Type same as in ``value``
:param bool optional: is object ``OPTIONAL`` in sequence
"""
- super(ObjectIdentifier, self).__init__(
- impl,
- expl,
- default,
- optional,
- _decoded,
- )
+ super(ObjectIdentifier, self).__init__(impl, expl, default, optional, _decoded)
self._value = value
if value is not None:
self._value = self._value_sanitize(value)
def ready(self):
return self._value is not None
- def copy(self):
- obj = self.__class__()
- obj._value = self._value
- obj.defines = self.defines
- obj.tag = self.tag
- obj._expl = self._expl
- obj.default = self.default
- obj.optional = self.optional
- obj.offset = self.offset
- obj.llen = self.llen
- obj.vlen = self.vlen
- obj.expl_lenindef = self.expl_lenindef
- obj.lenindef = self.lenindef
- obj.ber_encoded = self.ber_encoded
- return obj
+ def __getstate__(self):
+ return ObjectIdentifierState(
+ __version__,
+ self._value,
+ self.tag,
+ self._expl,
+ self.default,
+ self.optional,
+ self.offset,
+ self.llen,
+ self.vlen,
+ self.expl_lenindef,
+ self.lenindef,
+ self.ber_encoded,
+ self.defines,
+ )
+
+ def __setstate__(self, state):
+ super(ObjectIdentifier, self).__setstate__(state)
+ self._value = state.value
+ self.tag = state.tag
+ self._expl = state.expl
+ self.default = state.default
+ self.optional = state.optional
+ self.offset = state.offset
+ self.llen = state.llen
+ self.vlen = state.vlen
+ self.expl_lenindef = state.expl_lenindef
+ self.lenindef = state.lenindef
+ self.ber_encoded = state.ber_encoded
+ self.defines = state.defines
def __iter__(self):
self._assert_ready()
bounds=None, # dummy argument, workability for Integer.decode
):
super(Enumerated, self).__init__(
- value=value,
- impl=impl,
- expl=expl,
- default=default,
- optional=optional,
- _specs=_specs,
- _decoded=_decoded,
+ value, bounds, impl, expl, default, optional, _specs, _decoded,
)
if len(self.specs) == 0:
raise ValueError("schema must be specified")
raise InvalidValueType((self.__class__, int, str))
return value
- def copy(self):
- obj = self.__class__(_specs=self.specs)
- obj._value = self._value
- obj._bound_min = self._bound_min
- obj._bound_max = self._bound_max
- obj.tag = self.tag
- obj._expl = self._expl
- obj.default = self.default
- obj.optional = self.optional
- obj.offset = self.offset
- obj.llen = self.llen
- obj.vlen = self.vlen
- obj.expl_lenindef = self.expl_lenindef
- obj.lenindef = self.lenindef
- obj.ber_encoded = self.ber_encoded
- return obj
-
def __call__(
self,
value=None,
)
+def escape_control_unicode(c):
+ if unicat(c).startswith("C"):
+ c = repr(c).lstrip("u").strip("'")
+ return c
+
+
class CommonString(OctetString):
"""Common class for all strings
* - :py:class:`pyderasn.BMPString`
- utf-16-be
"""
- __slots__ = ("encoding",)
+ __slots__ = ()
def _value_sanitize(self, value):
value_raw = None
def pps(self, decode_path=(), no_unicode=False):
value = None
if self.ready:
- value = hexenc(bytes(self)) if no_unicode else self.__unicode__()
+ value = (
+ hexenc(bytes(self)) if no_unicode else
+ "".join(escape_control_unicode(c) for c in self.__unicode__())
+ )
yield _pp(
obj=self,
asn1_type_name=self.asn1_type_name,
return value
+PrintableStringState = namedtuple(
+ "PrintableStringState",
+ OctetStringState._fields + ("allowable_chars",),
+)
+
+
class PrintableString(AllowableCharsMixin, CommonString):
"""Printable string
_allowable_chars = frozenset(
(ascii_letters + digits + " '()+,-./:=?").encode("ascii")
)
+ _asterisk = frozenset("*".encode("ascii"))
+ _ampersand = frozenset("&".encode("ascii"))
+
+ def __init__(
+ self,
+ value=None,
+ bounds=None,
+ impl=None,
+ expl=None,
+ default=None,
+ optional=False,
+ _decoded=(0, 0, 0),
+ allow_asterisk=False,
+ allow_ampersand=False,
+ ):
+ """
+ :param allow_asterisk: allow asterisk character
+ :param allow_ampersand: allow ampersand character
+ """
+ if allow_asterisk:
+ self._allowable_chars |= self._asterisk
+ if allow_ampersand:
+ self._allowable_chars |= self._ampersand
+ super(PrintableString, self).__init__(
+ value, bounds, impl, expl, default, optional, _decoded,
+ )
def _value_sanitize(self, value):
value = super(PrintableString, self)._value_sanitize(value)
raise DecodeError("non-printable value")
return value
+ def __getstate__(self):
+ return PrintableStringState(
+ *super(PrintableString, self).__getstate__(),
+ **{"allowable_chars": self._allowable_chars}
+ )
+
+ def __setstate__(self, state):
+ super(PrintableString, self).__setstate__(state)
+ self._allowable_chars = state.allowable_chars
+
+ def __call__(
+ self,
+ value=None,
+ bounds=None,
+ impl=None,
+ expl=None,
+ default=None,
+ optional=None,
+ ):
+ return self.__class__(
+ value=value,
+ bounds=(
+ (self._bound_min, self._bound_max)
+ if bounds is None else bounds
+ ),
+ impl=self.tag if impl is None else impl,
+ expl=self._expl if expl is None else expl,
+ default=self.default if default is None else default,
+ optional=self.optional if optional is None else optional,
+ allow_asterisk=self._asterisk <= self._allowable_chars,
+ allow_ampersand=self._ampersand <= self._allowable_chars,
+ )
+
class TeletexString(CommonString):
__slots__ = ()
:param bool optional: is object ``OPTIONAL`` in sequence
"""
super(UTCTime, self).__init__(
- impl=impl,
- expl=expl,
- default=default,
- optional=optional,
- _decoded=_decoded,
+ None, None, impl, expl, default, optional, _decoded,
)
self._value = value
if value is not None:
asn1_type_name = "BMPString"
+ChoiceState = namedtuple("ChoiceState", (
+ "version",
+ "specs",
+ "value",
+ "tag",
+ "expl",
+ "default",
+ "optional",
+ "offset",
+ "llen",
+ "vlen",
+ "expl_lenindef",
+ "lenindef",
+ "ber_encoded",
+))
+
+
class Choice(Obj):
"""``CHOICE`` special type
default_obj._value = default_value
self.default = default_obj
if value is None:
- self._value = default_obj.copy()._value
+ self._value = copy(default_obj._value)
def _value_sanitize(self, value):
if isinstance(value, tuple) and len(value) == 2:
self._value[1].bered
)
- def copy(self):
- obj = self.__class__(schema=self.specs)
- obj._expl = self._expl
- obj.default = self.default
- obj.optional = self.optional
- obj.offset = self.offset
- obj.llen = self.llen
- obj.vlen = self.vlen
- obj.expl_lenindef = self.expl_lenindef
- obj.lenindef = self.lenindef
- obj.ber_encoded = self.ber_encoded
- value = self._value
- if value is not None:
- obj._value = (value[0], value[1].copy())
- return obj
+ def __getstate__(self):
+ return ChoiceState(
+ __version__,
+ self.specs,
+ copy(self._value),
+ self.tag,
+ self._expl,
+ self.default,
+ self.optional,
+ self.offset,
+ self.llen,
+ self.vlen,
+ self.expl_lenindef,
+ self.lenindef,
+ self.ber_encoded,
+ )
+
+ def __setstate__(self, state):
+ super(Choice, self).__setstate__(state)
+ self.specs = state.specs
+ self._value = state.value
+ self._expl = state.expl
+ self.default = state.default
+ self.optional = state.optional
+ self.offset = state.offset
+ self.llen = state.llen
+ self.vlen = state.vlen
+ self.expl_lenindef = state.expl_lenindef
+ self.lenindef = state.lenindef
+ self.ber_encoded = state.ber_encoded
def __eq__(self, their):
if isinstance(their, tuple) and len(their) == 2:
It could be useful for general decoding of some unspecified values:
- >>> PrimitiveTypes().decode(hexdec("0403666f6f"))[0].value
+ >>> PrimitiveTypes().decod(hexdec("0403666f6f")).value
OCTET STRING 3 bytes 666f6f
- >>> PrimitiveTypes().decode(hexdec("0203123456"))[0].value
+ >>> PrimitiveTypes().decod(hexdec("0203123456")).value
INTEGER 1193046
"""
__slots__ = ()
))
+AnyState = namedtuple("AnyState", (
+ "version",
+ "value",
+ "tag",
+ "expl",
+ "optional",
+ "offset",
+ "llen",
+ "vlen",
+ "expl_lenindef",
+ "lenindef",
+ "ber_encoded",
+ "defined",
+))
+
+
class Any(Obj):
"""``ANY`` special type
return False
return self.defined[1].bered
- def copy(self):
- obj = self.__class__()
- obj._value = self._value
- obj.tag = self.tag
- obj._expl = self._expl
- obj.optional = self.optional
- obj.offset = self.offset
- obj.llen = self.llen
- obj.vlen = self.vlen
- obj.expl_lenindef = self.expl_lenindef
- obj.lenindef = self.lenindef
- obj.ber_encoded = self.ber_encoded
- return obj
+ def __getstate__(self):
+ return AnyState(
+ __version__,
+ self._value,
+ self.tag,
+ self._expl,
+ self.optional,
+ self.offset,
+ self.llen,
+ self.vlen,
+ self.expl_lenindef,
+ self.lenindef,
+ self.ber_encoded,
+ self.defined,
+ )
+
+ def __setstate__(self, state):
+ super(Any, self).__setstate__(state)
+ self._value = state.value
+ self.tag = state.tag
+ self._expl = state.expl
+ self.optional = state.optional
+ self.offset = state.offset
+ self.llen = state.llen
+ self.vlen = state.vlen
+ self.expl_lenindef = state.expl_lenindef
+ self.lenindef = state.lenindef
+ self.ber_encoded = state.ber_encoded
+ self.defined = state.defined
def __eq__(self, their):
if isinstance(their, binary_type):
_decoded=(offset, 0, tlvlen),
)
obj.lenindef = True
- obj.tag = t
+ obj.tag = t.tobytes()
return obj, v[EOC_LEN:]
except DecodeError as err:
raise err.__class__(
optional=self.optional,
_decoded=(offset, 0, tlvlen),
)
- obj.tag = t
+ obj.tag = t.tobytes()
return obj, tail
def __repr__(self):
return decode_path + rel_path
+SequenceState = namedtuple("SequenceState", (
+ "version",
+ "specs",
+ "value",
+ "tag",
+ "expl",
+ "default",
+ "optional",
+ "offset",
+ "llen",
+ "vlen",
+ "expl_lenindef",
+ "lenindef",
+ "ber_encoded",
+))
+
+
class Sequence(Obj):
"""``SEQUENCE`` structure type
default_obj._value = default_value
self.default = default_obj
if value is None:
- self._value = default_obj.copy()._value
+ self._value = copy(default_obj._value)
@property
def ready(self):
return True
return any(value.bered for value in itervalues(self._value))
- def copy(self):
- obj = self.__class__(schema=self.specs)
- obj.tag = self.tag
- obj._expl = self._expl
- obj.default = self.default
- obj.optional = self.optional
- obj.offset = self.offset
- obj.llen = self.llen
- obj.vlen = self.vlen
- obj.expl_lenindef = self.expl_lenindef
- obj.lenindef = self.lenindef
- obj.ber_encoded = self.ber_encoded
- obj._value = {k: v.copy() for k, v in iteritems(self._value)}
- return obj
+ def __getstate__(self):
+ return SequenceState(
+ __version__,
+ self.specs,
+ {k: copy(v) for k, v in iteritems(self._value)},
+ self.tag,
+ self._expl,
+ self.default,
+ self.optional,
+ self.offset,
+ self.llen,
+ self.vlen,
+ self.expl_lenindef,
+ self.lenindef,
+ self.ber_encoded,
+ )
+
+ def __setstate__(self, state):
+ super(Sequence, self).__setstate__(state)
+ self.specs = state.specs
+ self._value = state.value
+ self.tag = state.tag
+ self._expl = state.expl
+ self.default = state.default
+ self.optional = state.optional
+ self.offset = state.offset
+ self.llen = state.llen
+ self.vlen = state.vlen
+ self.expl_lenindef = state.expl_lenindef
+ self.lenindef = state.lenindef
+ self.ber_encoded = state.ber_encoded
def __eq__(self, their):
if not isinstance(their, self.__class__):
return obj, tail
+SequenceOfState = namedtuple("SequenceOfState", (
+ "version",
+ "spec",
+ "value",
+ "bound_min",
+ "bound_max",
+ "tag",
+ "expl",
+ "default",
+ "optional",
+ "offset",
+ "llen",
+ "vlen",
+ "expl_lenindef",
+ "lenindef",
+ "ber_encoded",
+))
+
+
class SequenceOf(Obj):
"""``SEQUENCE OF`` sequence type
optional=False,
_decoded=(0, 0, 0),
):
- super(SequenceOf, self).__init__(
- impl,
- expl,
- default,
- optional,
- _decoded,
- )
+ super(SequenceOf, self).__init__(impl, expl, default, optional, _decoded)
if schema is None:
schema = getattr(self, "schema", None)
if schema is None:
default_obj._value = default_value
self.default = default_obj
if value is None:
- self._value = default_obj.copy()._value
+ self._value = copy(default_obj._value)
def _value_sanitize(self, value):
if issubclass(value.__class__, SequenceOf):
return True
return any(v.bered for v in self._value)
- def copy(self):
- obj = self.__class__(schema=self.spec)
- obj._bound_min = self._bound_min
- obj._bound_max = self._bound_max
- obj.tag = self.tag
- obj._expl = self._expl
- obj.default = self.default
- obj.optional = self.optional
- obj.offset = self.offset
- obj.llen = self.llen
- obj.vlen = self.vlen
- obj.expl_lenindef = self.expl_lenindef
- obj.lenindef = self.lenindef
- obj.ber_encoded = self.ber_encoded
- obj._value = [v.copy() for v in self._value]
- return obj
+ def __getstate__(self):
+ return SequenceOfState(
+ __version__,
+ self.spec,
+ [copy(v) for v in self._value],
+ self._bound_min,
+ self._bound_max,
+ self.tag,
+ self._expl,
+ self.default,
+ self.optional,
+ self.offset,
+ self.llen,
+ self.vlen,
+ self.expl_lenindef,
+ self.lenindef,
+ self.ber_encoded,
+ )
+
+ def __setstate__(self, state):
+ super(SequenceOf, self).__setstate__(state)
+ self.spec = state.spec
+ self._value = state.value
+ self._bound_min = state.bound_min
+ self._bound_max = state.bound_max
+ self.tag = state.tag
+ self._expl = state.expl
+ self.default = state.default
+ self.optional = state.optional
+ self.offset = state.offset
+ self.llen = state.llen
+ self.vlen = state.vlen
+ self.expl_lenindef = state.expl_lenindef
+ self.lenindef = state.lenindef
+ self.ber_encoded = state.ber_encoded
def __eq__(self, their):
if isinstance(their, self.__class__):
for pp in pps:
if hasattr(pp, "_fields"):
if (
- decode_path_only != () and
- pp.decode_path[:len(decode_path_only)] != decode_path_only
+ decode_path_only != () and
+ pp.decode_path[:len(decode_path_only)] != decode_path_only
):
continue
if pp.asn1_type_name == Choice.asn1_type_name:
decode_path_len_decrease=len(decode_path_only),
)
for row in pp_console_blob(
- pp,
- decode_path_len_decrease=len(decode_path_only),
+ pp,
+ decode_path_len_decrease=len(decode_path_only),
):
yield row
else: