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 = "∞"
+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(
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)
- except ValueError:
+ except (TypeError, ValueError):
raise DecodeError("invalid UTCTime format")
return value
else:
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)
- except ValueError:
+ except (TypeError, ValueError):
raise DecodeError(
"invalid GeneralizedTime (without ms) format",
)
elif len(value_decoded) >= LEN_YYYYMMDDHHMMSSDMZ:
try:
datetime.strptime(value_decoded, self.fmt_ms)
- except ValueError:
+ except (TypeError, ValueError):
raise DecodeError(
"invalid GeneralizedTime (with ms) format",
)
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
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),
))
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
_value.append(value)
- obj = self.__class__(
- value=_value,
- schema=spec,
- bounds=(self._bound_min, self._bound_max),
- impl=self.tag,
- expl=self._expl,
- default=self.default,
- optional=self.optional,
- _decoded=(offset, llen, vlen + (EOC_LEN if lenindef else 0)),
- )
+ try:
+ obj = self.__class__(
+ value=_value,
+ schema=spec,
+ bounds=(self._bound_min, self._bound_max),
+ impl=self.tag,
+ expl=self._expl,
+ default=self.default,
+ optional=self.optional,
+ _decoded=(offset, llen, vlen + (EOC_LEN if lenindef else 0)),
+ )
+ except BoundsError as err:
+ raise DecodeError(
+ msg=str(err),
+ klass=self.__class__,
+ decode_path=decode_path,
+ offset=offset,
+ )
if lenindef:
if v[:EOC_LEN].tobytes() != EOC:
raise DecodeError(