Source code for asn1vnparser._asn1vnparser

# -*- coding: utf-8 -*-

"""Main module."""

from typing import Any, List, Tuple, Union

import pyparsing as pp

from asn1vnparser import _grammar, jsonencoder


[docs]def parse_asn1_value( asn1_value: str, as_json: bool = False, parse_all: bool = True ) -> Union[Any, str, Tuple[Any, str], Tuple[str, str]]: r"""Converts ASN.1 value (mainly BuiltinValue in ITU-T Rec. X.680) to Python object. Args: asn1_value: a ``str`` representing ASN.1 value notation(s). as_json: Returns JSON when ``True``. parse_all: When True, it is assumed that the whole ``asn1_value`` represents an ASN.1 value. Returns: - When ``parse_all`` is True, ``result``. - When ``parse_all`` is False, a tuple of ``(result, rest)``, where ``result`` is: - When `as_json` = False, a Python object representation of ``asn1_value`` - When `as_json` = True, a JSON representation of ``asn1_value`` as `str` and ``rest`` is the remaining `str` from ``asn1_value`` after reading the value notation. Examples: >>> parse_asn1_value("123") # INTEGER 123 >>> parse_asn1_value("{TRUE, FALSE}") # SEQUENCE OF [True, False] >>> parse_asn1_value( ... "{field1 NULL, field2 '1204'H, field3 '01011010 01'B}" ... ) # SEQUENCE {'field1': None, 'field2': b'\x12\x04', 'field3': bitarray('0101101001')} >>> parse_asn1_value("alt1 : enum1") # CHOICE {'alt1': 'enum1'} >>> parse_asn1_value("alt1: enum1", as_json=True) # as_json '{"alt1": "enum1"}' >>> parse_asn1_value("blah blah") # raises when not foune # doctest: +ELLIPSIS Traceback (most recent call last): ... pyparsing.ParseException: ... >>> parse_asn1_value("alt1: enum1\n---this is remaining string---", as_json=True) # by default: parse_all=True. # doctest: +ELLIPSIS Traceback (most recent call last): ... pyparsing.ParseException: Expected end of text... >>> parse_asn1_value("alt1: enum1\n---this is remaining string---", as_json=True, parse_all=False) # as_json ('{"alt1": "enum1"}', '\n---this is remaining string---') """ if parse_all: result = _grammar.value_syntax.parseString(asn1_value, parseAll=True) obj = result[0].value if as_json: return jsonencoder.JSONEncoder().encode(obj) else: return obj else: gen = _grammar.value_syntax.scanString(asn1_value, maxMatches=1) results = list(gen) if len(results) == 0: raise pp.ParseException('value notation not found') result, start, end = results[0] obj = result[0].value rest = asn1_value[end:] if as_json: return (jsonencoder.JSONEncoder().encode(obj), rest) else: return (obj, rest)
[docs]def parse_asn1_value_assignment( asn1_val_assignment: str, as_json: bool = False, parse_all: bool = True ) -> Union[ _grammar.AsnValueAssignment, str, Tuple[_grammar.AsnValueAssignment, str], Tuple[str, str] ]: r"""Converts ASN.1 value assignment to Python object. Args: asn1_val_assignment: A ``str`` representing ASN.1 value assignment(s). as_json: Returns JSON when ``True``. parse_all: When True, it is assumed that the whole ``asn1_val_assignment`` represents an ASN.1 value assignment. Returns: - When ``parse_all`` is True, ``result``. - When ``parse_all`` is False, a tuple of ``(result, rest)``, where ``result`` is: - When `as_json` = False, parsing result as ``AsnValueAssignment``. - When `as_json` = True, a JSON representation of ``asn1_val_assignment`` as ``str`` and ``rest`` is the remaining `str` from ``asn1_val_assinment`` after reading the value assignment. Examples: >>> parse_asn1_value_assignment("valuename Typename ::= 1234") {'value_name': 'valuename', 'type_name': 'Typename', 'value': 1234} >>> parse_asn1_value_assignment("nonsense") # raises when not found # doctest: +ELLIPSIS Traceback (most recent call last): ... pyparsing.ParseException: ... >>> parse_asn1_value_assignment("valuename Typename ::= 1234\n...remainremain...") # doctest: +ELLIPSIS Traceback (most recent call last): ... pyparsing.ParseException: Expected end of text... >>> parse_asn1_value_assignment("valuename Typename ::= 1234\n...remainremain...", parse_all=False) ({'value_name': 'valuename', 'type_name': 'Typename', 'value': 1234}, '\n...remainremain...') """ if parse_all: result = _grammar.value_assignment_syntax.parseString( asn1_val_assignment, parseAll=parse_all) obj = result[0] if as_json: return jsonencoder.JSONEncoder().encode(obj.__dict__) else: return obj else: gen = _grammar.value_assignment_syntax.scanString( asn1_val_assignment, maxMatches=1) results = list(gen) if len(results) == 0: raise pp.ParseException('value assignment not found') result, start, end = results[0] obj = result[0] rest = asn1_val_assignment[end:] if as_json: return (jsonencoder.JSONEncoder().encode(obj.__dict__), rest) else: return (obj, rest)
[docs]def parse_asn1_value_assignments( asn1_val_assignments: str, as_json: bool = False) -> List[Union[_grammar.AsnValueAssignment, str]]: r"""Parses multiple ASN.1 value assignments. Examples: >>> parse_asn1_value_assignments('value1 INTEGER ::= 1\nvalue2 Type2 ::= the-value') [{'value_name': 'value1', 'type_name': 'INTEGER', 'value': 1}, {'value_name': 'value2', 'type_name': 'Type2', 'value': 'the-value'}] >>> parse_asn1_value_assignments('nonsense') # returns [] when not found [] >>> parse_asn1_value_assignments('value1 INTEGER ::= 1\nvalue2 Type2 ::= the-value', as_json=True) '[{"value_name": "value1", "type_name": "INTEGER", "value": 1}, {"value_name": "value2", "type_name": "Type2", "value": "the-value"}]' >>> parse_asn1_value_assignments('nonsense', as_json=True) # returns '[]' when not found '[]' """ def gen(): rest = asn1_val_assignments while True: try: obj, rest = parse_asn1_value_assignment(rest, parse_all=False) yield obj except pp.ParseException: return assignments = list(gen()) if as_json: return jsonencoder.JSONEncoder().encode([va.__dict__ for va in assignments]) else: return assignments