Pay attention that those values do **not** include anything related to
explicit tag. If you want to know information about it, then use:
-``expled`` (to know if explicit tag is set), ``expl_offset`` (it is
-lesser than ``offset``), ``expl_tlen``, ``expl_llen``, ``expl_vlen``
-(that actually equals to ordinary ``tlvlen``).
+
+* ``expled`` -- to know if explicit tag is set
+* ``expl_offset`` (it is lesser than ``offset``)
+* ``expl_tlen``,
+* ``expl_llen``
+* ``expl_vlen`` (that actually equals to ordinary ``tlvlen``)
+* ``fulloffset`` -- it equals to ``expl_offset`` if explicit tag is set,
+ ``offset`` otherwise
+* ``fulllen`` -- it equals to ``expl_len`` if explicit tag is set,
+ ``tlvlen`` otherwise
When error occurs, :py:exc:`pyderasn.DecodeError` is raised.
}
EOC = b"\x00\x00"
EOC_LEN = len(EOC)
+LENINDEF = b"\x80" # length indefinite mark
+LENINDEF_PP_CHAR = "I" if PY2 else "∞"
########################################################################
def expl_tlvlen(self):
return self.expl_tlen + self.expl_llen + self.expl_vlen
+ @property
+ def fulloffset(self):
+ return self.expl_offset if self.expled else self.offset
+
+ @property
+ def fulllen(self):
+ return self.expl_tlvlen if self.expled else self.tlvlen
+
+ def pps_lenindef(self, decode_path):
+ if self.lenindef:
+ yield _pp(
+ asn1_type_name="EOC",
+ obj_name="",
+ decode_path=decode_path,
+ offset=(
+ self.offset + self.tlvlen -
+ (EOC_LEN * 2 if self.expl_lenindef else EOC_LEN)
+ ),
+ tlen=1,
+ llen=1,
+ vlen=0,
+ bered=True,
+ )
+ if self.expl_lenindef:
+ yield _pp(
+ asn1_type_name="EOC",
+ obj_name="EXPLICIT",
+ decode_path=decode_path,
+ offset=self.expl_offset + self.expl_tlvlen - EOC_LEN,
+ tlen=1,
+ llen=1,
+ vlen=0,
+ bered=True,
+ )
+
class DecodePathDefBy(object):
"""DEFINED BY representation inside decode path
):
cols = []
if with_offsets:
- col = "%5d%s" % (
+ col = "%5d%s%s" % (
pp.offset,
(
" " if pp.expl_offset is None else
("-%d" % (pp.offset - pp.expl_offset))
),
+ LENINDEF_PP_CHAR if pp.expl_lenindef else " ",
)
cols.append(_colorize(col, "red", with_colours, ()))
- col = "[%d,%d,%4d]" % (pp.tlen, pp.llen, pp.vlen)
- col = _colorize(col, "green", with_colours, ())
- ber_deoffset = 0
- if pp.expl_lenindef:
- ber_deoffset += 2
- if pp.lenindef:
- ber_deoffset += 2
- col += (
- " " if ber_deoffset == 0 else
- _colorize(("-%d" % ber_deoffset), "red", with_colours)
+ col = "[%d,%d,%4d]%s" % (
+ pp.tlen,
+ pp.llen,
+ pp.vlen,
+ LENINDEF_PP_CHAR if pp.lenindef else " "
)
+ col = _colorize(col, "green", with_colours, ())
cols.append(col)
if len(pp.decode_path) > 0:
cols.append(" ." * (len(pp.decode_path)))
def pp_console_blob(pp):
- cols = [" " * len("XXXXXYY [X,X,XXXX]YY")]
+ cols = [" " * len("XXXXXYYZ [X,X,XXXX]Z")]
if len(pp.decode_path) > 0:
cols.append(" ." * (len(pp.decode_path) + 1))
if isinstance(pp.blob, binary_type):
expl_lenindef=self.expl_lenindef,
bered=self.bered,
)
+ for pp in self.pps_lenindef(decode_path):
+ yield pp
class Integer(Obj):
expl_vlen=self.expl_vlen if self.expled else None,
expl_lenindef=self.expl_lenindef,
)
+ for pp in self.pps_lenindef(decode_path):
+ yield pp
class BitString(Obj):
yield defined.pps(
decode_path=decode_path + (DecodePathDefBy(defined_by),)
)
+ for pp in self.pps_lenindef(decode_path):
+ yield pp
class OctetString(Obj):
yield defined.pps(
decode_path=decode_path + (DecodePathDefBy(defined_by),)
)
+ for pp in self.pps_lenindef(decode_path):
+ yield pp
class Null(Obj):
expl_vlen=self.expl_vlen if self.expled else None,
expl_lenindef=self.expl_lenindef,
)
+ for pp in self.pps_lenindef(decode_path):
+ yield pp
class ObjectIdentifier(Obj):
expl_vlen=self.expl_vlen if self.expled else None,
expl_lenindef=self.expl_lenindef,
)
+ for pp in self.pps_lenindef(decode_path):
+ yield pp
class Enumerated(Integer):
expl_vlen=self.expl_vlen if self.expled else None,
expl_lenindef=self.expl_lenindef,
)
+ for pp in self.pps_lenindef(decode_path):
+ yield pp
class UTF8String(CommonString):
if isinstance(value, datetime):
return value.strftime(self.fmt).encode("ascii")
if isinstance(value, binary_type):
- value_decoded = value.decode("ascii")
+ try:
+ value_decoded = value.decode("ascii")
+ except (UnicodeEncodeError, UnicodeDecodeError) as err:
+ raise DecodeError("invalid UTCTime encoding")
if len(value_decoded) == LEN_YYMMDDHHMMSSZ:
try:
datetime.strptime(value_decoded, self.fmt)
expl_vlen=self.expl_vlen if self.expled else None,
expl_lenindef=self.expl_lenindef,
)
+ for pp in self.pps_lenindef(decode_path):
+ yield pp
class GeneralizedTime(UTCTime):
self.fmt_ms if value.microsecond > 0 else self.fmt
).encode("ascii")
if isinstance(value, binary_type):
- value_decoded = value.decode("ascii")
+ try:
+ value_decoded = value.decode("ascii")
+ except (UnicodeEncodeError, UnicodeDecodeError) as err:
+ raise DecodeError("invalid GeneralizedTime encoding")
if len(value_decoded) == LEN_YYYYMMDDHHMMSSZ:
try:
datetime.strptime(value_decoded, self.fmt)
expl=self._expl,
default=self.default,
optional=self.optional,
- _decoded=(offset, 0, value.tlvlen),
+ _decoded=(offset, 0, value.fulllen),
)
obj._value = (choice, value)
return obj, tail
)
if self.ready:
yield self.value.pps(decode_path=decode_path + (self.choice,))
+ for pp in self.pps_lenindef(decode_path):
+ yield pp
class PrimitiveTypes(Choice):
yield defined.pps(
decode_path=decode_path + (DecodePathDefBy(defined_by),)
)
+ for pp in self.pps_lenindef(decode_path):
+ yield pp
########################################################################
("algorithm", ObjectIdentifier("1.2.3")),
("parameters", Any(Null()))
))
- AlgorithmIdentifier SEQUENCE[OBJECT IDENTIFIER 1.2.3, ANY 0500 OPTIONAL]
+ AlgorithmIdentifier SEQUENCE[algorithm: OBJECT IDENTIFIER 1.2.3; parameters: ANY 0500 OPTIONAL]
You can determine if value exists/set in the sequence and take its value:
continue
raise
- defined = get_def_by_path(ctx.get("defines", ()), sub_decode_path)
+ defined = get_def_by_path(ctx.get("_defines", ()), sub_decode_path)
if defined is not None:
defined_by, defined_spec = defined
if issubclass(value.__class__, SequenceOf):
)
value.defined = (defined_by, defined_value)
- value_len = value.expl_tlvlen if value.expled else value.tlvlen
+ value_len = value.fulllen
vlen += value_len
sub_offset += value_len
v = v_tail
for rel_path, schema in spec_defines:
defined = schema.get(value, None)
if defined is not None:
- ctx.setdefault("defines", []).append((
+ ctx.setdefault("_defines", []).append((
abs_decode_path(sub_decode_path[:-1], rel_path),
(value, defined),
))
_value = self._value.get(name)
if _value is None:
continue
- cols.append(repr(_value))
- return "%s[%s]" % (value, ", ".join(cols))
+ cols.append("%s: %s" % (name, repr(_value)))
+ return "%s[%s]" % (value, "; ".join(cols))
def pps(self, decode_path=()):
yield _pp(
if value is None:
continue
yield value.pps(decode_path=decode_path + (name,))
+ for pp in self.pps_lenindef(decode_path):
+ yield pp
class Set(Sequence):
decode_path=sub_decode_path,
ctx=ctx,
)
- value_len = value.expl_tlvlen if value.expled else value.tlvlen
+ value_len = value.fulllen
sub_offset += value_len
vlen += value_len
v = v_tail
decode_path=decode_path + (str(len(_value)),),
ctx=ctx,
)
- value_len = value.expl_tlvlen if value.expled else value.tlvlen
+ value_len = value.fulllen
sub_offset += value_len
vlen += value_len
v = v_tail
)
for i, value in enumerate(self._value):
yield value.pps(decode_path=decode_path + (str(i),))
+ for pp in self.pps_lenindef(decode_path):
+ yield pp
class SetOf(SequenceOf):